Merge branch 'temp' into nkw
[platform/framework/native/appfw.git] / src / io / FIo_FileImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FIo_FileImpl.cpp
19  * @brief       This is the implementation file for %_FileImpl class.
20  */
21
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/mount.h>
28 #include <limits.h>
29 #include <errno.h>
30 #include <new>
31 #include <unique_ptr.h>
32 #include <fcntl.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 #include <FBase_NativeError.h>
46
47 #include "FIo_FileImpl.h"
48 #include "FIo_NormalFile.h"
49 #include "FIo_DirectoryImpl.h"
50 #include "FIo_SecureFile.h"
51 #include "FIo_SecureIoUtil.h"
52 #include "FIo_IFileCore.h"
53 #include "FIo_FileUtil.h"
54 #include "FIo_FileLockImpl.h"
55
56 using namespace std;
57 using namespace Tizen::Base;
58 using namespace Tizen::App;
59 using namespace Tizen::System;
60
61 namespace Tizen { namespace Io
62 {
63
64 static const int _MAX_PATH_LENGTH = 128;
65 static const size_t _MAX_FILE_OPENMODE_LENGTH = 3;
66 static const char _INTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/internal";
67 static const char _EXTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/external";
68
69 struct _OspDir
70 {
71         char path[_MAX_PATH_LENGTH];
72         mode_t mode;
73         bool appPrivilege; // false: root privilege
74 };
75
76 struct _LinkDir
77 {
78         char srcPath[_MAX_PATH_LENGTH];
79         char destPath[_MAX_PATH_LENGTH];
80 };
81
82 struct _PathInfo
83 {
84     char pathName[_MAX_PATH_LENGTH];
85 };
86
87 _FileImpl::_FileImpl(void)
88         : __pCore(null)
89         , __read(false)
90         , __write(false)
91         , __truncate(false)
92         , __append(false)
93         , __pFileLockImpl(null)
94 {
95 }
96
97 _FileImpl::~_FileImpl(void)
98 {
99         delete __pCore;
100         if (__pFileLockImpl != null)
101         {
102                 __pFileLockImpl->__pFileImpl = null;
103         }
104 }
105
106 _FileImpl::_FileImpl(const _FileImpl& fileImpl)
107         : __pCore(null)
108         , __read(false)
109         , __write(false)
110         , __truncate(false)
111         , __append(false)
112 {
113         SysAssertf(false, "_FileImpl class does not support copy constructor.\n");
114 }
115
116 _FileImpl&
117 _FileImpl::operator =(const _FileImpl& fileImpl)
118 {
119         SysAssertf(false, "_FileImpl class does not support '=' operator.\n");
120
121         if (&fileImpl == this)
122         {
123                 return *this;
124         }
125
126         return *this;
127 }
128
129 bool
130 _FileImpl::VerifyFileOpenMode(const char* pOpenMode)
131 {
132         if (pOpenMode == null)
133         {
134                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
135                 return false;
136         }
137
138         if (strlen(pOpenMode) > _MAX_FILE_OPENMODE_LENGTH)
139         {
140                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
141                 return false;
142         }
143
144         switch (pOpenMode[0])
145         {
146         case 'r':
147                 __read = true;
148                 break;
149         case 'w':
150                 __write = true;
151                 __truncate = true;
152                 break;
153         case 'a':
154                 __write = true;
155                 __append = true;
156                 break;
157         default:
158                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
159                 return false;
160         }
161
162         switch (pOpenMode[1])
163         {
164         case '\0':
165                 break;
166         case '+':
167                 if (pOpenMode[2] == '\0' || pOpenMode[2] == 'b')
168                 {
169                         __read = true;
170                         __write = true;
171                         break;
172                 }
173                 else
174                 {
175                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
176                         return false;
177                 }
178         case 'b':
179                 if (pOpenMode[2] == '\0')
180                 {
181                         break;
182                 }
183                 else if (pOpenMode[2] == '+')
184                 {
185                         __read = true;
186                         __write = true;
187                         break;
188                 }
189                 else
190                 {
191                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
192                         return false;
193                 }
194         default:
195                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
196                 return false;
197         }
198
199         return true;
200 }
201
202 result
203 _FileImpl::Construct(const String& filePath, const String& openMode, bool createParentDirsToo, const ByteBuffer* pSecretKey)
204 {
205         SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
206         result r = E_SUCCESS;
207
208         if (openMode.Contains(L'r') == true)
209         {
210                 SysTryReturnResult(NID_IO, !createParentDirsToo, E_INVALID_ARG,
211                                 "The specified createParentDirsToo cannot be used without file creation mode.");
212         }
213
214         if (createParentDirsToo == true)
215         {
216                 String dirPath;
217                 int position = 0;
218
219                 r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, position);
220                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_INVALID_ARG, "The specified filePath is invalid.");
221                 SysTryReturnResult(NID_IO, !(position == 0), E_INVALID_ARG, "The specified filePath is invalid.");
222
223                 r = filePath.SubString(0, position, dirPath);
224                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to extract dir path.", GetErrorMessage(r));
225
226                 r = Directory::Create(dirPath, true);
227                 if (IsFailed(r))
228                 {
229                         if (r == E_FILE_ALREADY_EXIST)
230                         {
231                                 r = E_SUCCESS;
232                         }
233                         else
234                         {
235                                 SysPropagate(NID_IO, r);
236                                 return r;
237                         }
238                 }
239         }
240
241         unique_ptr<char[]> pOpenMode(_StringConverter::CopyToCharArrayN(openMode));
242         SysTryReturnResult(NID_IO, pOpenMode != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
243
244         return Construct(filePath, pOpenMode.get(), pSecretKey);
245 }
246
247 result
248 _FileImpl::Construct(const String& filePath, const char* pOpenMode, const ByteBuffer* pSecretKey)
249 {
250         SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
251         result r = E_SUCCESS;
252
253         bool isValidOpenMode = VerifyFileOpenMode(pOpenMode);
254         SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
255
256         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
257                         E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
258
259         if (!__truncate && IsFileExist(filePath))
260         {
261                 r = _SecureIoUtil::CheckSecureFileHeader(filePath, pSecretKey);
262                 if (r == E_END_OF_FILE)
263                 {
264                         r = E_IO; //for security error
265                 }
266                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
267         }
268
269         if (pSecretKey == null)
270         {
271                 unique_ptr<_NormalFile> pNormalFile(new (std::nothrow) _NormalFile());
272                 SysTryReturnResult(NID_IO, pNormalFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
273
274                 r = pNormalFile->Construct(filePath, pOpenMode);
275                 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
276                 __pCore = pNormalFile.release();
277         }
278         else
279         {
280                 unique_ptr<_SecureFile> pSecureFile(new (std::nothrow) _SecureFile(__read, __write, __truncate, __append));
281                 SysTryReturnResult(NID_IO, pSecureFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
282
283                 r = pSecureFile->Construct(filePath, pOpenMode, pSecretKey);
284                 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
285                 __pCore = pSecureFile.release();
286         }
287
288         return E_SUCCESS;
289 }
290
291 result
292 _FileImpl::ReadN(char** buffer, int& length)
293 {
294         result r = E_SUCCESS;
295         if (__pCore != null)
296         {
297                 _NormalFile* pNormalFile = dynamic_cast< _NormalFile* > (__pCore);
298                 if (pNormalFile != null)
299                 {
300                         r = pNormalFile->ReadN(buffer, length);
301                 }
302         }
303         else
304         {
305                 r = E_INVALID_OPERATION;
306         }
307
308         return r;
309 }
310
311 result
312 _FileImpl::Read(ByteBuffer& buffer)
313 {
314         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
315         SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
316         return __pCore->Read(buffer);
317 }
318
319 int
320 _FileImpl::Read(void* buffer, int length)
321 {
322         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
323         SysTryReturn(NID_IO, __read == true, 0, E_ILLEGAL_ACCESS, "[E_ILLEGAL_ACCESS] File is not opened for reading.");
324         return __pCore->Read(buffer, length);
325 }
326
327 result
328 _FileImpl::Read(String& buffer)
329 {
330         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
331         SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
332         return __pCore->Read(buffer);
333 }
334
335 result
336 _FileImpl::Write(const ByteBuffer& buffer)
337 {
338         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
339         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
340         return __pCore->Write(buffer);
341 }
342
343 result
344 _FileImpl::Write(const void* buffer, int length)
345 {
346         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
347         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
348         return __pCore->Write(buffer, length);
349 }
350
351 result
352 _FileImpl::Write(const String& buffer)
353 {
354         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
355         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
356         return __pCore->Write(buffer);
357 }
358
359 result
360 _FileImpl::Flush(void)
361 {
362         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
363         return __pCore->Flush();
364 }
365
366 int
367 _FileImpl::Tell(void) const
368 {
369         SysTryReturnResult(NID_IO, __pCore != null, -1, "File is not constructed! Construct destined file first! ");
370         return __pCore->Tell();
371 }
372
373 result
374 _FileImpl::Seek(FileSeekPosition position, long offset)
375 {
376         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
377         return __pCore->Seek(position, offset);
378 }
379
380 result
381 _FileImpl::Truncate(int length)
382 {
383         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
384         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
385         return __pCore->Truncate(length);
386 }
387
388 String
389 _FileImpl::GetName(void) const
390 {
391         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
392         return __pCore->GetName();
393 }
394
395 FILE*
396 _FileImpl::GetFilePointer(void) const
397 {
398         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
399         return __pCore->GetFilePointer();
400 }
401
402 FileLock*
403 _FileImpl::LockN(FileLockType lockType)
404 {
405         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
406         return LockN(lockType, FILE_LOCK_MODE_BLOCKING, 0, 0);
407 }
408
409 FileLock*
410 _FileImpl::LockN(FileLockType lockType, int offset, int length)
411 {
412         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
413         return LockN(lockType, FILE_LOCK_MODE_BLOCKING, offset, length);
414 }
415
416 FileLock*
417 _FileImpl::TryToLockN(FileLockType lockType)
418 {
419         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
420         return LockN(lockType, FILE_LOCK_MODE_NON_BLOCKING, 0, 0);
421 }
422
423 FileLock*
424 _FileImpl::TryToLockN(FileLockType lockType, int offset, int length)
425 {
426         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
427         return LockN(lockType, FILE_LOCK_MODE_NON_BLOCKING, offset, length);
428 }
429
430 FileLock*
431 _FileImpl::LockN(FileLockType lockType, _FileLockMode lockMode, int offset, int length)
432 {
433         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
434         SysTryReturn(NID_IO, offset >= 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified offset is negative.");
435         SysTryReturn(NID_IO, length >= 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified length is negative.");
436
437         struct flock lock;
438         switch (lockType)
439         {
440         case FILE_LOCK_SHARED:
441                 SysTryReturn(NID_IO, __read == true, null, E_INVALID_OPERATION, "[E_INVALID_OPERATION] File is not opened for reading.");
442                 lock.l_type = F_RDLCK;
443                 break;
444         case FILE_LOCK_EXCLUSIVE:
445                 SysTryReturn(NID_IO, __write == true, null, E_INVALID_OPERATION, "[E_INVALID_OPERATION] File is not opened for writing.");
446                 lock.l_type = F_WRLCK;
447                 break;
448         default:
449                 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock type is invalid.");
450                 return null;
451         }
452
453         int fd = fileno(this->GetFilePointer());
454         int lockCommand = -1;
455         int ret = -1;
456         switch (lockMode)
457         {
458         case FILE_LOCK_MODE_BLOCKING:
459                 lockCommand = F_SETLKW;
460                 break;
461         case FILE_LOCK_MODE_NON_BLOCKING:
462         {
463                 lockCommand = F_SETLK;
464                 break;
465         }
466         default:
467                 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock mode is invalid.");
468                 return null;
469         }
470
471         lock.l_whence = SEEK_SET;
472         lock.l_start = offset;
473         lock.l_len = length;
474         lock.l_pid = getpid();
475
476         ret = fcntl(fd, lockCommand, &lock);
477         if (ret != 0)
478         {
479                 result r = E_SUCCESS;
480                 switch (errno)
481                 {
482                 case ENOLCK:
483                         r = E_MAX_EXCEEDED;
484                         break;
485                 case EDEADLK:
486                 {
487                         if (lockMode == FILE_LOCK_MODE_BLOCKING)
488                         {
489                                 r = E_WOULD_DEADLOCK;
490                         }
491                         else
492                         {
493                                 r = E_SYSTEM;
494                         }
495                         break;
496                 }
497                 case EAGAIN:
498                         // fall through
499                 case EACCES:
500                         if (lockMode == FILE_LOCK_MODE_NON_BLOCKING)
501                         {
502                                 r = E_OBJECT_LOCKED;
503                                 break;
504                         }
505                         // else fall through
506                 case EFAULT:
507                         // fall through
508                 case EBADF:
509                         r = E_SYSTEM;
510                         break;
511                 default:
512                         r = _NativeError::ConvertNativeErrorToResult(errno, true);
513                         break;
514                 }
515
516                 SysLogException(NID_IO, r, "[%s] Aquiring file lock of type (%d) is failed, errno: %d (%s)", GetErrorMessage(r), lockType, errno, strerror(errno));
517                 return null;
518         }
519
520         unique_ptr<FileLock> pFileLock(_FileLockImpl::CreateFileLockInstanceN(this, lockType, lock.l_start, lock.l_len, lock.l_pid));
521         SysTryReturn(NID_IO, pFileLock != null, null, GetLastResult(), "[%s] Propagating to caller....", GetErrorMessage(GetLastResult()));
522         __pFileLockImpl = _FileLockImpl::GetInstance(*pFileLock);
523         SetLastResult(E_SUCCESS);
524         return pFileLock.release();
525 }
526
527 result
528 _FileImpl::Remove(const String& filePath)
529 {
530         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
531                                           E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
532         return _FileUtil::Remove(filePath);
533 }
534
535 result
536 _FileImpl::Move(const String& oldFilePath, const String& newFilePath)
537 {
538         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(oldFilePath, _AppInfo::IsOspCompat()) == true,
539                                           E_INVALID_ARG, " [%ls] is not compatible.", oldFilePath.GetPointer());
540
541         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(newFilePath, _AppInfo::IsOspCompat()) == true,
542                                           E_INVALID_ARG, " [%ls] is not compatible.", newFilePath.GetPointer());
543         return _FileUtil::Move(oldFilePath, newFilePath);
544 }
545
546 result
547 _FileImpl::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
548 {
549         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(srcFilePath, _AppInfo::IsOspCompat()) == true,
550                                           E_INVALID_ARG, " [%ls] is not compatible.", srcFilePath.GetPointer());
551
552         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(destFilePath, _AppInfo::IsOspCompat()) == true,
553                                           E_INVALID_ARG, " [%ls] is not compatible.", destFilePath.GetPointer());
554         return _FileUtil::Copy(srcFilePath, destFilePath, failIfExist);
555 }
556
557 result
558 _FileImpl::GetAttributes(const String& filePath, FileAttributes& attribute)
559 {
560         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
561                                           E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
562         return _FileUtil::GetAttributes(filePath, attribute);
563 }
564
565 String
566 _FileImpl::GetFileName(const String& filePath)
567 {
568         return _FileUtil::GetFileName(filePath);
569 }
570
571 String
572 _FileImpl::GetFileExtension(const String& filePath)
573 {
574         return _FileUtil::GetFileExtension(filePath);
575 }
576
577 bool
578 _FileImpl::IsFileExist(const String& filePath)
579 {
580         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
581                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
582
583         return _FileUtil::IsFileExist(filePath);
584 }
585
586 result
587 _FileImpl::ConvertToSecureFile(const String& plainFilePath, const String& secureFilePath,
588                                                            const ByteBuffer& key)
589 {
590         return _FileUtil::ConvertToSecureFile(plainFilePath, secureFilePath, &key);
591 }
592
593 bool
594 _FileImpl::IsAppPath(const String& filePath)
595 {
596         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
597                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
598
599         return _FileUtil::IsAppPath(filePath);
600 }
601
602 bool
603 _FileImpl::IsMediaPath(const String& filePath)
604 {
605         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
606                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
607
608         return _FileUtil::IsMediaPath(filePath);
609 }
610
611 bool
612 _FileImpl::IsSystemPath(const String& filePath)
613 {
614         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
615                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
616
617         return _FileUtil::IsSystemPath(filePath);
618 }
619
620 bool
621 _FileImpl::VerifyFilePath(const String& filePath, _FilePathType pathType)
622 {
623         return _FileUtil::VerifyFilePath(filePath, pathType);
624 }
625
626 bool
627 _FileImpl::VerifyFilePathCompatibility(const String& filePath, bool ospCompat)
628 {
629         if (ospCompat == true)
630         {
631                 if (filePath[0] != L'/')
632                 {
633                         return false;
634                 }
635         }
636         int length = filePath.GetLength();
637         if (length > 0)
638         {
639                 return true;
640         }
641         return false;
642 }
643
644 _FileImpl*
645 _FileImpl::GetInstance(File& file)
646 {
647         return file.__pFileImpl;
648 }
649
650 const _FileImpl*
651 _FileImpl::GetInstance(const File& file)
652 {
653         return file.__pFileImpl;
654 }
655
656 result
657 _FileImpl::ConvertVirtualToPhysicalPath(const String& virtualPath, String& physicalPath) // for 2.0 app
658 {
659         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(virtualPath, _AppInfo::IsOspCompat()) == true,
660                         E_INVALID_ARG, "[E_INVALID_ARG] %ls is not compatible.", virtualPath.GetPointer());
661
662         const wchar_t* virtualPathPrefix[] =
663         {
664                 L"/Home/Share2",
665                 L"/Home/Share",
666                 L"/Home",
667                 L"/Res",
668                 L"/Share2",
669                 L"/Share/AppControl",
670                 L"/Share",
671                 //L"/HomeExt",
672                 //L"/ShareExt",
673                 //L"/Share2Ext",
674                 //L"/NPKI",
675                 L"/Media",
676                 L"/Storagecard/Media",
677                 //L"/Storagecard/NPKI",
678         };
679         result r = E_SUCCESS;
680         int count = sizeof(virtualPathPrefix)/sizeof(wchar_t*);
681         int i = 0;
682
683         for (i = 0; i < count; i++)
684         {
685                 SysLog(NID_IO, "[V2P] i: %d, path: %ls", i, virtualPathPrefix[i]);
686                 if (virtualPath.StartsWith(virtualPathPrefix[i], 0) == true)
687                 {
688                         break;
689                 }
690         }
691         SysTryReturnResult(NID_IO, i != count, E_INVALID_ARG, "The path (%ls) is not matched.",
692                         virtualPath.GetPointer());
693
694         int prefixLen = String(virtualPathPrefix[i]).GetLength();
695         if (virtualPath.GetLength() > prefixLen)
696         {
697                 wchar_t ch = '\0';
698
699                 r = virtualPath.GetCharAt(prefixLen, ch);
700                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
701                                 GetErrorMessage(r), virtualPath.GetPointer());
702
703                 if (ch != L'/')
704                 {
705                         physicalPath.Clear();
706                         SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
707                                         virtualPath.GetPointer());
708
709                         return E_INVALID_ARG;
710                 }
711         }
712
713         String subPath;
714         virtualPath.SubString(wcslen(virtualPathPrefix[i]), subPath);
715
716         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
717         SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
718         String homePath = pApp->GetAppRootPath();
719         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
720
721         switch (i)
722         {
723         case 0:
724                 physicalPath = homePath + L"data/Share2";
725                 break;
726         case 1:
727                 physicalPath = homePath + L"data/Share";
728                 break;
729         case 2:
730                 physicalPath = homePath + L"data";
731                 break;
732         case 3:
733                 physicalPath = homePath + L"res";
734                 break;
735         case 4:
736                 physicalPath = ospCompatSharedPath + L"share2";
737                 break;
738         case 5:
739                 physicalPath = ospCompatSharedPath + L"share/AppControl";
740                 break;
741         case 6:
742                 physicalPath = ospCompatSharedPath + L"share";
743                 break;
744         case 7:
745                 physicalPath = Tizen::System::Environment::GetMediaPath();
746                 physicalPath.SetLength(physicalPath.GetLength() - 1);
747                 break;
748         case 8:
749                 physicalPath = Tizen::System::Environment::GetExternalStoragePath();
750                 physicalPath.SetLength(physicalPath.GetLength() - 1);
751                 break;
752         default:
753                 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
754                                 virtualPath.GetPointer());
755                 return E_INVALID_ARG;
756         }
757
758         if (subPath.IsEmpty() == false)
759         {
760                 physicalPath.Append(subPath);
761         }
762
763         return r;
764 }
765
766 result
767 _FileImpl::ConvertPhysicalToVirtualPath(const String& physicalPath, String& virtualPath) // for 2.0 app
768 {
769         result r = E_SUCCESS;
770         const wchar_t* homeSubDir[] = {
771                 L"/data/Share2",
772                 L"/data/Share",
773                 L"/data",
774                 L"/res",
775         };
776         const wchar_t* ospHomeSubDir[] = {
777                 L"/share2",
778                 L"/share/AppControl",
779                 L"/share",
780         };
781         String subPath;
782         int homeSubDirCount = sizeof(homeSubDir)/sizeof(wchar_t*);
783         int ospHomeSubDirCount = sizeof(ospHomeSubDir)/sizeof(wchar_t*);
784         int baseDirLen = 0;
785         int i = 0;
786
787         SysLog(NID_IO, "[P2V] physicalPath: %ls", physicalPath.GetPointer());
788
789         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
790         SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
791         String homePath = pApp->GetAppRootPath();
792         homePath.SetLength(homePath.GetLength() - 1);
793
794         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
795         ospCompatSharedPath.SetLength(ospCompatSharedPath.GetLength() - 1);
796
797         String mediaPath = Tizen::System::Environment::GetMediaPath();
798         mediaPath.SetLength(mediaPath.GetLength() - 1);
799
800         String externalPath = Tizen::System::Environment::GetExternalStoragePath();
801         externalPath.SetLength(externalPath.GetLength() - 1);
802
803         if (physicalPath.StartsWith(homePath, 0) == true)
804         {
805                 physicalPath.SubString(homePath.GetLength(), subPath);
806
807                 for (i = 0; i < homeSubDirCount; i++)
808                 {
809                         SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, homeSubDir[i]);
810                         if (subPath.StartsWith(homeSubDir[i], 0) == true)
811                         {
812                                 break;
813                         }
814                 }
815                 SysTryReturnResult(NID_IO, i != homeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
816                                 physicalPath.GetPointer());
817
818                 baseDirLen = homePath.GetLength() + String(homeSubDir[i]).GetLength();
819
820                 switch (i)
821                 {
822                 case 0:
823                         virtualPath = L"/Home/Share2";
824                         break;
825                 case 1:
826                         virtualPath = L"/Home/Share";
827                         break;
828                 case 2:
829                         virtualPath = L"/Home";
830                         break;
831                 case 3:
832                         virtualPath = L"/Res";
833                         break;
834                 default:
835                         break;
836                 }
837
838         }
839         else if (physicalPath.StartsWith(ospCompatSharedPath, 0) == true)
840         {
841                 physicalPath.SubString(ospCompatSharedPath.GetLength(), subPath);
842
843                 for (i = 0; i < ospHomeSubDirCount; i++)
844                 {
845                         SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, ospHomeSubDir[i]);
846                         if (subPath.StartsWith(ospHomeSubDir[i], 0) == true)
847                         {
848                                 break;
849                         }
850                 }
851                 SysTryReturnResult(NID_IO, i != ospHomeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
852                                 physicalPath.GetPointer());
853
854                 baseDirLen = ospCompatSharedPath.GetLength() + String(ospHomeSubDir[i]).GetLength();
855
856                 switch (i)
857                 {
858                 case 0:
859                         virtualPath = L"/Share2";
860                         break;
861                 case 1:
862                         virtualPath = L"/Share/AppControl";
863                         break;
864                 case 2:
865                         virtualPath = L"/Share";
866                         break;
867                 default:
868                         break;
869                 }
870         }
871         else if (physicalPath.StartsWith(mediaPath, 0) == true)
872         {
873                 SysLog(NID_IO, "[P2V] media");
874                 virtualPath = L"/Media";
875                 baseDirLen = mediaPath.GetLength();
876         }
877         else if (physicalPath.StartsWith(externalPath, 0) == true)
878         {
879                 SysLog(NID_IO, "[P2V] external media");
880                 virtualPath = L"/Storagecard/Media";
881                 baseDirLen = externalPath.GetLength();
882         }
883         else
884         {
885                 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
886                                 physicalPath.GetPointer());
887
888                 return E_INVALID_ARG;
889         }
890
891         if (physicalPath.GetLength() > baseDirLen)
892         {
893                 wchar_t ch = '\0';
894
895                 r = physicalPath.GetCharAt(baseDirLen, ch);
896                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
897                                 GetErrorMessage(r), physicalPath.GetPointer());
898
899                 if (ch != L'/')
900                 {
901                         virtualPath.Clear();
902                         SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
903                                         physicalPath.GetPointer());
904
905                         return E_INVALID_ARG;
906                 }
907         }
908
909         subPath.Clear();
910         physicalPath.SubString(baseDirLen, subPath);
911
912         if (subPath.IsEmpty() == false)
913         {
914                 virtualPath.Append(subPath);
915         }
916
917         return r;
918 }
919
920 }} // Tizen::Io