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