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