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