2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FIo_FileImpl.cpp
20 * @brief This is the implementation file for %_FileImpl class.
27 #include <sys/types.h>
28 #include <sys/mount.h>
32 #include <unique_ptr.h>
35 #include <FBaseSysLog.h>
36 #include <FAppPkgPackageInfo.h>
37 #include <FIoDirectory.h>
40 #include <FSysEnvironment.h>
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>
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"
58 using namespace Tizen::Base;
59 using namespace Tizen::App;
60 using namespace Tizen::System;
62 namespace Tizen { namespace Io
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";
73 char path[_MAX_PATH_LENGTH];
75 bool appPrivilege; // false: root privilege
80 char srcPath[_MAX_PATH_LENGTH];
81 char destPath[_MAX_PATH_LENGTH];
86 char destPath[_MAX_PATH_LENGTH];
89 _FileImpl::_FileImpl(void)
95 , __pFileLockImpl(null)
99 _FileImpl::~_FileImpl(void)
102 if (__pFileLockImpl != null)
104 __pFileLockImpl->__pFileImpl = null;
108 _FileImpl::_FileImpl(const _FileImpl& fileImpl)
115 SysAssertf(false, "_FileImpl class does not support copy constructor.\n");
119 _FileImpl::operator =(const _FileImpl& fileImpl)
121 SysAssertf(false, "_FileImpl class does not support '=' operator.\n");
123 if (&fileImpl == this)
132 _FileImpl::VerifyFileOpenMode(const char* pOpenMode)
134 if (pOpenMode == null)
136 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
140 if (strlen(pOpenMode) > _MAX_FILE_OPENMODE_LENGTH)
142 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
146 switch (pOpenMode[0])
160 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
164 switch (pOpenMode[1])
169 if (pOpenMode[2] == '\0' || pOpenMode[2] == 'b')
177 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
181 if (pOpenMode[2] == '\0')
185 else if (pOpenMode[2] == '+')
193 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
197 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
205 _FileImpl::Construct(const String& filePath, const String& openMode, bool createParentDirsToo, const ByteBuffer* pSecretKey)
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;
210 if (openMode.Contains(L'r') == true)
212 SysTryReturnResult(NID_IO, !createParentDirsToo, E_INVALID_ARG,
213 "The specified createParentDirsToo cannot be used without file creation mode.");
216 if (createParentDirsToo == true)
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.");
225 r = filePath.SubString(0, position, dirPath);
226 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to extract dir path.", GetErrorMessage(r));
228 r = Directory::Create(dirPath, true);
231 if (r == E_FILE_ALREADY_EXIST)
237 SysPropagate(NID_IO, r);
243 unique_ptr<char[]> pOpenMode(_StringConverter::CopyToCharArrayN(openMode));
244 SysTryReturnResult(NID_IO, pOpenMode != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
246 return Construct(filePath, pOpenMode.get(), pSecretKey);
250 _FileImpl::Construct(const String& filePath, const char* pOpenMode, const ByteBuffer* pSecretKey)
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;
255 bool isValidOpenMode = VerifyFileOpenMode(pOpenMode);
256 SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
258 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
259 E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
261 if (!__truncate && IsFileExist(filePath))
263 r = _SecureIoUtil::CheckSecureFileHeader(filePath, pSecretKey);
264 if (r == E_END_OF_FILE)
266 r = E_IO; //for security error
268 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
271 if (pSecretKey == null)
273 unique_ptr<_NormalFile> pNormalFile(new (std::nothrow) _NormalFile());
274 SysTryReturnResult(NID_IO, pNormalFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
276 r = pNormalFile->Construct(filePath, pOpenMode);
277 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
278 __pCore = pNormalFile.release();
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.");
285 r = pSecureFile->Construct(filePath, pOpenMode, pSecretKey);
286 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
287 __pCore = pSecureFile.release();
294 _FileImpl::ReadN(char** buffer, int& length)
296 result r = E_SUCCESS;
299 _NormalFile* pNormalFile = dynamic_cast< _NormalFile* > (__pCore);
300 if (pNormalFile != null)
302 r = pNormalFile->ReadN(buffer, length);
307 r = E_INVALID_OPERATION;
314 _FileImpl::Read(ByteBuffer& buffer)
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);
322 _FileImpl::Read(void* buffer, int length)
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);
330 _FileImpl::Read(String& buffer)
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);
338 _FileImpl::Write(const ByteBuffer& buffer)
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);
346 _FileImpl::Write(const void* buffer, int length)
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);
354 _FileImpl::Write(const String& buffer)
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);
362 _FileImpl::Flush(void)
364 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
365 return __pCore->Flush();
369 _FileImpl::Tell(void) const
371 SysTryReturnResult(NID_IO, __pCore != null, -1, "File is not constructed! Construct destined file first! ");
372 return __pCore->Tell();
376 _FileImpl::Seek(FileSeekPosition position, long offset)
378 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
379 return __pCore->Seek(position, offset);
383 _FileImpl::Truncate(int length)
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);
391 _FileImpl::GetName(void) const
393 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
394 return __pCore->GetName();
398 _FileImpl::GetFilePointer(void) const
400 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
401 return __pCore->GetFilePointer();
405 _FileImpl::LockN(FileLockType lockType)
407 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
408 return LockN(lockType, FILE_LOCK_MODE_BLOCKING, 0, 0);
412 _FileImpl::LockN(FileLockType lockType, int offset, int length)
414 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
415 return LockN(lockType, FILE_LOCK_MODE_BLOCKING, offset, length);
419 _FileImpl::TryToLockN(FileLockType lockType)
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);
426 _FileImpl::TryToLockN(FileLockType lockType, int offset, int length)
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);
433 _FileImpl::LockN(FileLockType lockType, _FileLockMode lockMode, int offset, int length)
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.");
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;
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;
451 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock type is invalid.");
455 int fd = fileno(this->GetFilePointer());
456 int lockCommand = -1;
460 case FILE_LOCK_MODE_BLOCKING:
461 lockCommand = F_SETLKW;
463 case FILE_LOCK_MODE_NON_BLOCKING:
465 lockCommand = F_SETLK;
469 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock mode is invalid.");
473 lock.l_whence = SEEK_SET;
474 lock.l_start = offset;
476 lock.l_pid = getpid();
478 ret = fcntl(fd, lockCommand, &lock);
481 result r = E_SUCCESS;
489 if (lockMode == FILE_LOCK_MODE_BLOCKING)
491 r = E_WOULD_DEADLOCK;
502 if (lockMode == FILE_LOCK_MODE_NON_BLOCKING)
514 r = _NativeError::ConvertNativeErrorToResult(errno, true);
518 SysLogException(NID_IO, r, "[%s] Aquiring file lock of type (%d) is failed, errno: %d (%s)", GetErrorMessage(r), lockType, errno, strerror(errno));
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();
530 _FileImpl::Remove(const String& filePath)
532 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
533 E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
534 return _FileUtil::Remove(filePath);
538 _FileImpl::Move(const String& oldFilePath, const String& newFilePath)
540 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(oldFilePath, _AppInfo::IsOspCompat()) == true,
541 E_INVALID_ARG, " [%ls] is not compatible.", oldFilePath.GetPointer());
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);
549 _FileImpl::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
551 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(srcFilePath, _AppInfo::IsOspCompat()) == true,
552 E_INVALID_ARG, " [%ls] is not compatible.", srcFilePath.GetPointer());
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);
560 _FileImpl::GetAttributes(const String& filePath, FileAttributes& attribute)
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);
568 _FileImpl::GetFileName(const String& filePath)
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());
575 return _FileUtil::GetFileName(filePath);
579 _FileImpl::GetFileExtension(const String& filePath)
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());
586 return _FileUtil::GetFileExtension(filePath);
590 _FileImpl::IsFileExist(const String& filePath)
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());
595 return _FileUtil::IsFileExist(filePath);
599 _FileImpl::ConvertToSecureFile(const String& plainFilePath, const String& secureFilePath,
600 const ByteBuffer& key)
602 return _FileUtil::ConvertToSecureFile(plainFilePath, secureFilePath, &key);
606 _FileImpl::IsAppPath(const String& filePath)
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());
611 return _FileUtil::IsAppPath(filePath);
615 _FileImpl::IsMediaPath(const String& filePath)
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());
620 return _FileUtil::IsMediaPath(filePath);
624 _FileImpl::IsSystemPath(const String& filePath)
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());
629 return _FileUtil::IsSystemPath(filePath);
633 _FileImpl::VerifyFilePath(const String& filePath, _FilePathType pathType)
635 return _FileUtil::VerifyFilePath(filePath, pathType);
639 _FileImpl::CleanDirectories(const String& appRootPath, const String& pkgId)
641 char removeCmd[PATH_MAX] = {0, };
644 String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
645 ospSharePkgIdPath.Append(L"share/");
646 ospSharePkgIdPath.Append(pkgId);
648 String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
649 ospShare2PkgIdPath.Append(L"share2/");
650 ospShare2PkgIdPath.Append(pkgId);
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());
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());
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());
666 memset(removeCmd, 0, PATH_MAX);
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());
677 // This method is called by package installer backend.
679 _FileImpl::PrepareDataCaging(const String& appRootPath, const String& pkgId)
683 bool internalInstalled = true;
684 result r = E_SUCCESS;
686 SysLog(NID_IO, "[data_caging] PrepareDataCaging() was called by installer backend, appRootPath: %ls, packageId: %ls",
687 appRootPath.GetPointer(), pkgId.GetPointer());
689 if (CleanDirectories(appRootPath, pkgId) == false)
691 SysLog(NID_IO, "CleanDirectories() failed.");
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));
699 // Check whether package is installed on internal storage or not
700 r = appRootPath.IndexOf("/opt/storage/sdcard", 0, index);
703 internalInstalled = false;
707 internalInstalled = true;
712 if (internalInstalled == true)
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.");
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());
720 SysTryCatch(NID_IO, CreateOspInternalDirectories(pkgId) == true, r = E_SYSTEM, E_SYSTEM,
721 "[E_SYSTEM] fail to create OSP Internal directories");
725 String appExRootPath(appRootPath);
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.");
733 ret = mkdir(pAppExRootPath.get(), 0705);
734 if (ret == -1 && errno != 17) // EEXIST
736 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
737 strerror(errno), pAppExRootPath.get(), 0705);
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");
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);
755 SysLog(NID_IO, "[data_caging] PrepareDataCaging() succeeded.");
768 SysLog(NID_IO, "[data_caging] PrepareDataCaging() failed.");
776 _FileImpl::FinalizeDataCaging(const String& appRootPath) // for 2.0 app
778 static const struct _PathInfo mountPath[] =
789 //{ "./lost+found" },
793 { "./opt/var/kdb/db" },
794 { "./opt/storage/sdcard" },
800 { "./sys/kernel/debug" },
817 { "./Storagecard/Media" },
820 { "./HomeExt/Share" },
821 { "./HomeExt/Share2" },
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.");
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());
832 for (int i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
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);
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)
846 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
847 mountFlag, errno, strerror(errno));
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)
856 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
857 mountFlag, errno, strerror(errno));
861 SysLog(NID_IO, "[data_caging] FinalizeDataCaging() succeeded, appRootPath: %ls", appRootPath.GetPointer());
866 _FileImpl::GetAvailableUid(void)
872 _FileImpl::CreateOspApplicationDirectories(const String& appRootPath, const String& pkgId) // for 2.1 app
874 struct _OspDir appSubDir[] =
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 }
885 result r = E_SUCCESS;
887 SysTryReturn(NID_IO, CleanDirectories(appRootPath, pkgId) == true, false, E_SYSTEM,
888 "[E_SYSTEM] Failed to clean directories for 2.0 application compatibility.");
890 unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
891 SysTryReturn(NID_IO, pAppRootPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
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());
896 uid = GetAvailableUid();
900 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); ++i)
902 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
903 if (ret == -1 && errno != 17) // EEXIST
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);
910 if (appSubDir[i].appPrivilege)
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);
919 if (access("./shared/data", F_OK) == 0)
921 SysTryCatch(NID_IO, system("chown -R 5000:5000 ./shared/data") != -1, , E_SYSTEM,
922 "[E_SYSTEM] chown() failed");
924 // XXX: Temp code for supporting old share directory.
925 else if (access("./share", F_OK) == 0)
927 SysTryCatch(NID_IO, system("rm -rf ./shared/data") != -1, , E_SYSTEM,
928 "[E_SYSTEM] Failed to remove ./shared/data directory");
930 SysTryCatch(NID_IO, rename("./share", "./shared/data") == 0, , E_SYSTEM,
931 "[E_SYSTEM] Failed to rename share directory (%d, %s)", errno, strerror(errno));
933 SysTryCatch(NID_IO, system("chown -R 5000:5000 ./shared/data") != -1, , E_SYSTEM,
934 "[E_SYSTEM] chown() failed");
936 SysTryCatch(NID_IO, chmod("./shared/data", 0755) == 0, , E_SYSTEM, "[E_SYSTEM] chmod() failed");
942 SysLog(NID_IO, "_FileImpl::CreateOspApplicationDirectories() succeeded.");
952 _FileImpl::CreateOspInternalDirectories(const String& pkgId) // for 2.0 app
957 struct _OspDir appSubDir[] =
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
974 struct _OspDir mediaDir[] =
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 }
983 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
984 String ospShareAppIdPath(L"share/");
985 String ospShare2AppIdPath(L"share2/");
986 result r = E_SUCCESS;
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));
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));
996 uid = GetAvailableUid();
998 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
1000 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
1001 if (ret == -1 && errno != 17) // EEXIST
1003 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1004 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
1007 if (appSubDir[i].appPrivilege)
1009 ret = chown(appSubDir[i].path, uid, uid);
1012 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1013 strerror(errno), appSubDir[i].path, uid);
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
1025 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1026 strerror(errno), pOspShareAppIdPath.get(), 0705);
1029 ret = chown(pOspShareAppIdPath.get(), uid, uid);
1032 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1033 strerror(errno), pOspShareAppIdPath.get(), uid);
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
1043 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1044 strerror(errno), pOspShare2AppIdPath.get(), 0705);
1047 ret = chown(pOspShare2AppIdPath.get(), uid, uid);
1050 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1051 strerror(errno), pOspShare2AppIdPath.get(), uid);
1056 for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); ++i)
1058 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
1059 if (ret == -1 && errno != 17) // EEXIST
1061 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1062 strerror(errno), mediaDir[i].path, mediaDir[i].mode);
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);
1072 // XXX: shared directory is not supported for 2.0 applications
1074 if (access("./shared/data", F_OK) == 0)
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);
1081 SysTryReturn(NID_IO, system("rm -rf ./shared/data") != -1, false, E_SYSTEM,
1082 "[E_SYSTEM] rmdir() failed, path: ./shared/data");
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");
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");
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");
1100 // TODO: Need to test this method.
1102 _FileImpl::CreateOspExternalDirectories(const String& pkgId)
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
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 }
1123 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
1125 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
1126 if (ret == -1 && errno != 17) // EEXIST
1128 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1129 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
1132 if (appSubDir[i].appPrivilege)
1134 ret = chown(appSubDir[i].path, uid, uid);
1137 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1138 strerror(errno), appSubDir[i].path, uid);
1145 for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); i++)
1147 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
1148 if (ret == -1 && errno != 17) // EEXIST
1150 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1151 strerror(errno), mediaDir[i].path, mediaDir[i].mode);
1161 _FileImpl::CreateSlpDirectories(void)
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 }
1187 for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
1189 ret = mkdir(slpDir[i].path, slpDir[i].mode);
1190 if (ret == -1 && errno != 17) // EEXIST
1192 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1193 strerror(errno), slpDir[i].path, slpDir[i].mode);
1202 _FileImpl::CreateSymbolicLink(void)
1204 struct _LinkDir linkDirList[] = {
1205 { "/opt/home", "./home" },
1206 { "/opt/home/root", "./root" },
1207 { "/mnt/mmc", "./sdcard" }
1210 for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
1212 int ret = symlink(linkDirList[i].srcPath, linkDirList[i].destPath);
1213 if (ret == -1 && errno != 17) // EEXIST
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);
1225 _FileImpl::VerifyFilePathCompatibility(const String& filePath, bool ospCompat)
1227 if (ospCompat == true)
1229 if (filePath[0] != L'/')
1234 int length = filePath.GetLength();
1243 _FileImpl::GetInstance(File& file)
1245 return file.__pFileImpl;
1249 _FileImpl::GetInstance(const File& file)
1251 return file.__pFileImpl;
1255 _FileImpl::ConvertVirtualToPhysicalPath(const String& virtualPath, String& physicalPath) // for 2.0 app
1257 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(virtualPath, _AppInfo::IsOspCompat()) == true,
1258 E_INVALID_ARG, "[E_INVALID_ARG] %ls is not compatible.", virtualPath.GetPointer());
1260 const wchar_t* virtualPathPrefix[] =
1267 L"/Share/AppControl",
1274 L"/Storagecard/Media",
1275 //L"/Storagecard/NPKI",
1277 result r = E_SUCCESS;
1278 int count = sizeof(virtualPathPrefix)/sizeof(wchar_t*);
1281 for (i = 0; i < count; i++)
1283 SysLog(NID_IO, "[V2P] i: %d, path: %ls", i, virtualPathPrefix[i]);
1284 if (virtualPath.StartsWith(virtualPathPrefix[i], 0) == true)
1289 SysTryReturnResult(NID_IO, i != count, E_INVALID_ARG, "The path (%ls) is not matched.",
1290 virtualPath.GetPointer());
1292 int prefixLen = String(virtualPathPrefix[i]).GetLength();
1293 if (virtualPath.GetLength() > prefixLen)
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());
1303 physicalPath.Clear();
1304 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1305 virtualPath.GetPointer());
1307 return E_INVALID_ARG;
1312 virtualPath.SubString(wcslen(virtualPathPrefix[i]), subPath);
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();
1322 physicalPath = homePath + L"data/Share2";
1325 physicalPath = homePath + L"data/Share";
1328 physicalPath = homePath + L"data";
1331 physicalPath = homePath + L"res";
1334 physicalPath = ospCompatSharedPath + L"share2";
1337 physicalPath = ospCompatSharedPath + L"share/AppControl";
1340 physicalPath = ospCompatSharedPath + L"share";
1343 physicalPath = Tizen::System::Environment::GetMediaPath();
1346 physicalPath = Tizen::System::Environment::GetExternalStoragePath() + L"Media";
1349 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1350 virtualPath.GetPointer());
1351 return E_INVALID_ARG;
1354 if (subPath.IsEmpty() == false)
1356 physicalPath.Append(subPath);
1363 _FileImpl::ConvertPhysicalToVirtualPath(const String& physicalPath, String& virtualPath) // for 2.0 app
1365 result r = E_SUCCESS;
1366 const wchar_t* homeSubDir[] = {
1372 const wchar_t* ospHomeSubDir[] = {
1374 L"/share/AppControl",
1378 int homeSubDirCount = sizeof(homeSubDir)/sizeof(wchar_t*);
1379 int ospHomeSubDirCount = sizeof(ospHomeSubDir)/sizeof(wchar_t*);
1383 SysLog(NID_IO, "[P2V] physicalPath: %ls", physicalPath.GetPointer());
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);
1390 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
1391 ospCompatSharedPath.SetLength(ospCompatSharedPath.GetLength() - 1);
1393 String mediaPath = Tizen::System::Environment::GetMediaPath();
1394 mediaPath.SetLength(mediaPath.GetLength() - 1);
1396 String externalPath = Tizen::System::Environment::GetExternalStoragePath();
1397 externalPath.SetLength(externalPath.GetLength() - 1);
1399 if (physicalPath.StartsWith(homePath, 0) == true)
1401 physicalPath.SubString(homePath.GetLength(), subPath);
1403 for (i = 0; i < homeSubDirCount; i++)
1405 SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, homeSubDir[i]);
1406 if (subPath.StartsWith(homeSubDir[i], 0) == true)
1411 SysTryReturnResult(NID_IO, i != homeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1412 physicalPath.GetPointer());
1414 baseDirLen = homePath.GetLength() + String(homeSubDir[i]).GetLength();
1419 virtualPath = L"/Home/Share2";
1422 virtualPath = L"/Home/Share";
1425 virtualPath = L"/Home";
1428 virtualPath = L"/Res";
1435 else if (physicalPath.StartsWith(ospCompatSharedPath, 0) == true)
1437 physicalPath.SubString(ospCompatSharedPath.GetLength(), subPath);
1439 for (i = 0; i < ospHomeSubDirCount; i++)
1441 SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, ospHomeSubDir[i]);
1442 if (subPath.StartsWith(ospHomeSubDir[i], 0) == true)
1447 SysTryReturnResult(NID_IO, i != ospHomeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1448 physicalPath.GetPointer());
1450 baseDirLen = ospCompatSharedPath.GetLength() + String(ospHomeSubDir[i]).GetLength();
1455 virtualPath = L"/Share2";
1458 virtualPath = L"/Share/AppControl";
1461 virtualPath = L"/Share";
1467 else if (physicalPath.StartsWith(mediaPath, 0) == true)
1469 SysLog(NID_IO, "[P2V] media");
1470 virtualPath = L"/Media";
1471 baseDirLen = mediaPath.GetLength();
1473 else if (physicalPath.StartsWith(externalPath, 0) == true)
1475 SysLog(NID_IO, "[P2V] external media");
1476 virtualPath = L"/Storagecard/Media";
1477 baseDirLen = externalPath.GetLength();
1481 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1482 physicalPath.GetPointer());
1484 return E_INVALID_ARG;
1487 if (physicalPath.GetLength() > baseDirLen)
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());
1497 virtualPath.Clear();
1498 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1499 physicalPath.GetPointer());
1501 return E_INVALID_ARG;
1506 physicalPath.SubString(baseDirLen, subPath);
1508 if (subPath.IsEmpty() == false)
1510 virtualPath.Append(subPath);