2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FIo_FileImpl.cpp
19 * @brief This is the implementation file for %_FileImpl class.
26 #include <sys/types.h>
27 #include <sys/mount.h>
31 #include <unique_ptr.h>
34 #include <FBaseSysLog.h>
35 #include <FAppPkgPackageInfo.h>
36 #include <FIoDirectory.h>
39 #include <FSysEnvironment.h>
41 #include <FBase_StringConverter.h>
42 #include <FApp_AppInfo.h>
43 #include <FAppPkg_PackageInfoImpl.h>
44 #include <FSys_EnvironmentImpl.h>
45 #include <FBase_NativeError.h>
47 #include "FIo_FileImpl.h"
48 #include "FIo_NormalFile.h"
49 #include "FIo_DirectoryImpl.h"
50 #include "FIo_SecureFile.h"
51 #include "FIo_SecureIoUtil.h"
52 #include "FIo_IFileCore.h"
53 #include "FIo_FileUtil.h"
54 #include "FIo_FileLockImpl.h"
57 using namespace Tizen::Base;
58 using namespace Tizen::App;
59 using namespace Tizen::System;
61 namespace Tizen { namespace Io
64 static const int _MAX_PATH_LENGTH = 128;
65 static const int _APP_UID = 5000;
66 static const size_t _MAX_FILE_OPENMODE_LENGTH = 3;
67 static const char _INTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/internal";
68 static const char _EXTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/external";
72 char path[_MAX_PATH_LENGTH];
74 bool appPrivilege; // false: root privilege
79 char srcPath[_MAX_PATH_LENGTH];
80 char destPath[_MAX_PATH_LENGTH];
85 char destPath[_MAX_PATH_LENGTH];
88 _FileImpl::_FileImpl(void)
94 , __pFileLockImpl(null)
98 _FileImpl::~_FileImpl(void)
101 if (__pFileLockImpl != null)
103 __pFileLockImpl->__pFileImpl = null;
107 _FileImpl::_FileImpl(const _FileImpl& fileImpl)
114 SysAssertf(false, "_FileImpl class does not support copy constructor.\n");
118 _FileImpl::operator =(const _FileImpl& fileImpl)
120 SysAssertf(false, "_FileImpl class does not support '=' operator.\n");
122 if (&fileImpl == this)
131 _FileImpl::VerifyFileOpenMode(const char* pOpenMode)
133 if (pOpenMode == null)
135 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
139 if (strlen(pOpenMode) > _MAX_FILE_OPENMODE_LENGTH)
141 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
145 switch (pOpenMode[0])
159 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
163 switch (pOpenMode[1])
168 if (pOpenMode[2] == '\0' || pOpenMode[2] == 'b')
176 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
180 if (pOpenMode[2] == '\0')
184 else if (pOpenMode[2] == '+')
192 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
196 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
204 _FileImpl::Construct(const String& filePath, const String& openMode, bool createParentDirsToo, const ByteBuffer* pSecretKey)
206 SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
207 result r = E_SUCCESS;
209 if (openMode.Contains(L'r') == true)
211 SysTryReturnResult(NID_IO, !createParentDirsToo, E_INVALID_ARG,
212 "The specified createParentDirsToo cannot be used without file creation mode.");
215 if (createParentDirsToo == true)
220 r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, position);
221 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_INVALID_ARG, "The specified filePath is invalid.");
222 SysTryReturnResult(NID_IO, !(position == 0), E_INVALID_ARG, "The specified filePath is invalid.");
224 r = filePath.SubString(0, position, dirPath);
225 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to extract dir path.", GetErrorMessage(r));
227 r = Directory::Create(dirPath, true);
230 if (r == E_FILE_ALREADY_EXIST)
236 SysPropagate(NID_IO, r);
242 unique_ptr<char[]> pOpenMode(_StringConverter::CopyToCharArrayN(openMode));
243 SysTryReturnResult(NID_IO, pOpenMode != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
245 return Construct(filePath, pOpenMode.get(), pSecretKey);
249 _FileImpl::Construct(const String& filePath, const char* pOpenMode, const ByteBuffer* pSecretKey)
251 SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
252 result r = E_SUCCESS;
254 bool isValidOpenMode = VerifyFileOpenMode(pOpenMode);
255 SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
257 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
258 E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
260 if (!__truncate && IsFileExist(filePath))
262 r = _SecureIoUtil::CheckSecureFileHeader(filePath, pSecretKey);
263 if (r == E_END_OF_FILE)
265 r = E_IO; //for security error
267 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
270 if (pSecretKey == null)
272 unique_ptr<_NormalFile> pNormalFile(new (std::nothrow) _NormalFile());
273 SysTryReturnResult(NID_IO, pNormalFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
275 r = pNormalFile->Construct(filePath, pOpenMode);
276 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
277 __pCore = pNormalFile.release();
281 unique_ptr<_SecureFile> pSecureFile(new (std::nothrow) _SecureFile(__read, __write, __truncate, __append));
282 SysTryReturnResult(NID_IO, pSecureFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
284 r = pSecureFile->Construct(filePath, pOpenMode, pSecretKey);
285 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
286 __pCore = pSecureFile.release();
293 _FileImpl::ReadN(char** buffer, int& length)
295 result r = E_SUCCESS;
298 _NormalFile* pNormalFile = dynamic_cast< _NormalFile* > (__pCore);
299 if (pNormalFile != null)
301 r = pNormalFile->ReadN(buffer, length);
306 r = E_INVALID_OPERATION;
313 _FileImpl::Read(ByteBuffer& buffer)
315 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
316 SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
317 return __pCore->Read(buffer);
321 _FileImpl::Read(void* buffer, int length)
323 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
324 SysTryReturn(NID_IO, __read == true, 0, E_ILLEGAL_ACCESS, "[E_ILLEGAL_ACCESS] File is not opened for reading.");
325 return __pCore->Read(buffer, length);
329 _FileImpl::Read(String& buffer)
331 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
332 SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
333 return __pCore->Read(buffer);
337 _FileImpl::Write(const ByteBuffer& buffer)
339 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
340 SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
341 return __pCore->Write(buffer);
345 _FileImpl::Write(const void* buffer, int length)
347 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
348 SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
349 return __pCore->Write(buffer, length);
353 _FileImpl::Write(const String& buffer)
355 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
356 SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
357 return __pCore->Write(buffer);
361 _FileImpl::Flush(void)
363 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
364 return __pCore->Flush();
368 _FileImpl::Tell(void) const
370 SysTryReturnResult(NID_IO, __pCore != null, -1, "File is not constructed! Construct destined file first! ");
371 return __pCore->Tell();
375 _FileImpl::Seek(FileSeekPosition position, long offset)
377 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
378 return __pCore->Seek(position, offset);
382 _FileImpl::Truncate(int length)
384 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
385 SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
386 return __pCore->Truncate(length);
390 _FileImpl::GetName(void) const
392 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
393 return __pCore->GetName();
397 _FileImpl::GetFilePointer(void) const
399 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
400 return __pCore->GetFilePointer();
404 _FileImpl::LockN(FileLockType lockType)
406 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
407 return LockN(lockType, FILE_LOCK_MODE_BLOCKING, 0, 0);
411 _FileImpl::LockN(FileLockType lockType, int offset, int length)
413 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
414 return LockN(lockType, FILE_LOCK_MODE_BLOCKING, offset, length);
418 _FileImpl::TryToLockN(FileLockType lockType)
420 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
421 return LockN(lockType, FILE_LOCK_MODE_NON_BLOCKING, 0, 0);
425 _FileImpl::TryToLockN(FileLockType lockType, int offset, int length)
427 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
428 return LockN(lockType, FILE_LOCK_MODE_NON_BLOCKING, offset, length);
432 _FileImpl::LockN(FileLockType lockType, _FileLockMode lockMode, int offset, int length)
434 SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
435 SysTryReturn(NID_IO, offset >= 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified offset is negative.");
436 SysTryReturn(NID_IO, length >= 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified length is negative.");
441 case FILE_LOCK_SHARED:
442 SysTryReturn(NID_IO, __read == true, null, E_INVALID_OPERATION, "[E_INVALID_OPERATION] File is not opened for reading.");
443 lock.l_type = F_RDLCK;
445 case FILE_LOCK_EXCLUSIVE:
446 SysTryReturn(NID_IO, __write == true, null, E_INVALID_OPERATION, "[E_INVALID_OPERATION] File is not opened for writing.");
447 lock.l_type = F_WRLCK;
450 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock type is invalid.");
454 int fd = fileno(this->GetFilePointer());
455 int lockCommand = -1;
459 case FILE_LOCK_MODE_BLOCKING:
460 lockCommand = F_SETLKW;
462 case FILE_LOCK_MODE_NON_BLOCKING:
464 lockCommand = F_SETLK;
468 SysLogException(NID_IO, E_INVALID_ARG, "[E_INVALID_ARG] The specified lock mode is invalid.");
472 lock.l_whence = SEEK_SET;
473 lock.l_start = offset;
475 lock.l_pid = getpid();
477 ret = fcntl(fd, lockCommand, &lock);
480 result r = E_SUCCESS;
488 if (lockMode == FILE_LOCK_MODE_BLOCKING)
490 r = E_WOULD_DEADLOCK;
501 if (lockMode == FILE_LOCK_MODE_NON_BLOCKING)
513 r = _NativeError::ConvertNativeErrorToResult(errno, true);
517 SysLogException(NID_IO, r, "[%s] Aquiring file lock of type (%d) is failed, errno: %d (%s)", GetErrorMessage(r), lockType, errno, strerror(errno));
521 unique_ptr<FileLock> pFileLock(_FileLockImpl::CreateFileLockInstanceN(this, lockType, lock.l_start, lock.l_len, lock.l_pid));
522 SysTryReturn(NID_IO, pFileLock != null, null, GetLastResult(), "[%s] Propagating to caller....", GetErrorMessage(GetLastResult()));
523 __pFileLockImpl = _FileLockImpl::GetInstance(*pFileLock);
524 SetLastResult(E_SUCCESS);
525 return pFileLock.release();
529 _FileImpl::Remove(const String& filePath)
531 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
532 E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
533 return _FileUtil::Remove(filePath);
537 _FileImpl::Move(const String& oldFilePath, const String& newFilePath)
539 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(oldFilePath, _AppInfo::IsOspCompat()) == true,
540 E_INVALID_ARG, " [%ls] is not compatible.", oldFilePath.GetPointer());
542 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(newFilePath, _AppInfo::IsOspCompat()) == true,
543 E_INVALID_ARG, " [%ls] is not compatible.", newFilePath.GetPointer());
544 return _FileUtil::Move(oldFilePath, newFilePath);
548 _FileImpl::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
550 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(srcFilePath, _AppInfo::IsOspCompat()) == true,
551 E_INVALID_ARG, " [%ls] is not compatible.", srcFilePath.GetPointer());
553 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(destFilePath, _AppInfo::IsOspCompat()) == true,
554 E_INVALID_ARG, " [%ls] is not compatible.", destFilePath.GetPointer());
555 return _FileUtil::Copy(srcFilePath, destFilePath, failIfExist);
559 _FileImpl::GetAttributes(const String& filePath, FileAttributes& attribute)
561 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
562 E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
563 return _FileUtil::GetAttributes(filePath, attribute);
567 _FileImpl::GetFileName(const String& filePath)
569 return _FileUtil::GetFileName(filePath);
573 _FileImpl::GetFileExtension(const String& filePath)
575 return _FileUtil::GetFileExtension(filePath);
579 _FileImpl::IsFileExist(const String& filePath)
581 SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
582 false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
584 return _FileUtil::IsFileExist(filePath);
588 _FileImpl::ConvertToSecureFile(const String& plainFilePath, const String& secureFilePath,
589 const ByteBuffer& key)
591 return _FileUtil::ConvertToSecureFile(plainFilePath, secureFilePath, &key);
595 _FileImpl::IsAppPath(const String& filePath)
597 SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
598 false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
600 return _FileUtil::IsAppPath(filePath);
604 _FileImpl::IsMediaPath(const String& filePath)
606 SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
607 false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
609 return _FileUtil::IsMediaPath(filePath);
613 _FileImpl::IsSystemPath(const String& filePath)
615 SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
616 false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
618 return _FileUtil::IsSystemPath(filePath);
622 _FileImpl::VerifyFilePath(const String& filePath, _FilePathType pathType)
624 return _FileUtil::VerifyFilePath(filePath, pathType);
628 _FileImpl::CleanDirectories(const String& appRootPath, const String& pkgId)
630 char removeCmd[PATH_MAX] = {0, };
633 String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
634 ospSharePkgIdPath.Append(L"share/");
635 ospSharePkgIdPath.Append(pkgId);
637 String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
638 ospShare2PkgIdPath.Append(L"share2/");
639 ospShare2PkgIdPath.Append(pkgId);
642 r = Directory::Remove(ospSharePkgIdPath, true);
643 SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[%s] Failed to remove directory (%ls)",
644 GetErrorMessage(r), ospSharePkgIdPath.GetPointer());
646 r = Directory::Remove(ospShare2PkgIdPath, true);
647 SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[%s] Failed to remove directory (%ls)",
648 GetErrorMessage(r), ospShare2PkgIdPath.GetPointer());
650 sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
651 ret = system(removeCmd);
652 SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to remove directory (%ls)",
653 ospSharePkgIdPath.GetPointer());
655 memset(removeCmd, 0, PATH_MAX);
657 sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
658 ret = system(removeCmd);
659 SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to remove directory (%ls)",
660 ospShare2PkgIdPath.GetPointer());
666 // This method is called by package installer backend.
668 _FileImpl::PrepareDataCaging(const String& appRootPath, const String& pkgId)
672 bool internalInstalled = true;
673 result r = E_SUCCESS;
675 SysSecureLog(NID_IO, "[data_caging] PrepareDataCaging() was called by installer backend, appRootPath: %ls, packageId: %ls",
676 appRootPath.GetPointer(), pkgId.GetPointer());
678 if (CleanDirectories(appRootPath, pkgId) == false)
680 SysLog(NID_IO, "CleanDirectories() failed.");
684 pCwd = get_current_dir_name();
685 SysTryCatch(NID_IO, pCwd != null, r = E_SYSTEM, E_SYSTEM,
686 "[E_SYSTEM] get_current_dir_name() was failed, errno: %d (%s).", errno, strerror(errno));
688 // Check whether package is installed on internal storage or not
689 r = appRootPath.IndexOf("/opt/storage/sdcard", 0, index);
692 internalInstalled = false;
696 internalInstalled = true;
701 if (internalInstalled == true)
703 unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
704 SysTryCatch(NID_IO, pAppRootPath != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
706 SysTryCatch(NID_IO, chdir(pAppRootPath.get()) == 0, r = E_SYSTEM, E_SYSTEM,
707 "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pAppRootPath.get());
709 SysTryCatch(NID_IO, CreateOspInternalDirectories(appRootPath, pkgId) == true, r = E_SYSTEM, E_SYSTEM,
710 "[E_SYSTEM] fail to create OSP Internal directories");
714 String appExRootPath(appRootPath);
718 appExRootPath.Append(pkgId);
719 unique_ptr<char[]> pAppExRootPath(_StringConverter::CopyToCharArrayN(appExRootPath));
720 SysTryCatch(NID_IO, pAppExRootPath != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
722 ret = mkdir(pAppExRootPath.get(), 0705);
723 if (ret == -1 && errno != 17) // EEXIST
725 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
726 strerror(errno), pAppExRootPath.get(), 0705);
730 SysTryCatch(NID_IO, chdir(pAppExRootPath.get()) == 0, r = E_SYSTEM, E_SYSTEM,
731 "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pAppExRootPath.get());
732 SysTryCatch(NID_IO, CreateOspExternalDirectories(pkgId) == true, r = E_SYSTEM, E_SYSTEM,
733 "[E_SYSTEM] fail to create OSP External directories");
736 SysTryCatch(NID_IO, CreateSlpDirectories() == true, r = E_SYSTEM, E_SYSTEM,
737 "[E_SYSTEM] fail to create SLP directories");
738 SysTryCatch(NID_IO, CreateSymbolicLink() == true, r = E_SYSTEM, E_SYSTEM,
739 "[E_SYSTEM] Fail to create symbolic link.");
740 SysTryCatch(NID_IO, chdir(pCwd) == 0, r = E_SYSTEM, E_SYSTEM,
741 "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pCwd);
744 SysLog(NID_IO, "[data_caging] PrepareDataCaging() succeeded.");
757 SysLog(NID_IO, "[data_caging] PrepareDataCaging() failed.");
765 _FileImpl::FinalizeDataCaging(const String& appRootPath) // for 2.0 app
767 static const struct _PathInfo mountPath[] =
778 //{ "./lost+found" },
782 { "./opt/var/kdb/db" },
783 { "./opt/storage/sdcard" },
790 { "./sys/kernel/debug" },
807 { "./Storagecard/Media" },
810 { "./HomeExt/Share" },
811 { "./HomeExt/Share2" },
815 unique_ptr< char[] > pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
816 SysTryReturn(NID_IO, pAppRootPath != null, false, E_OUT_OF_MEMORY,
817 "[E_OUT_OF_MEMORY] The memory is insufficient.");
819 SysTryReturn(NID_IO, chdir(pAppRootPath.get()) == 0, false, E_SYSTEM,
820 "[E_SYSTEM] chdir() failed (%d, %s), path: %ls", errno, strerror(errno), appRootPath.GetPointer());
822 for (int i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
824 int ret = umount2(mountPath[i].destPath, MNT_DETACH);
825 SysTryLog(NID_IO, ret == 0, "umount2() errno: %d (%s)", errno, strerror(errno));
826 SysTryReturn(NID_IO, ret == 0 || errno == EINVAL || errno == ENOENT, false, E_SYSTEM,
827 "[E_SYSTEM] umount2() failed (%d, %s), path: %s", errno, strerror(errno), mountPath[i].destPath);
830 char* pkgId = strrchr(pAppRootPath.get(), '/');
831 char mountFlag[_MAX_PATH_LENGTH] = { 0, };
832 sprintf(mountFlag, "%s/%s", _INTERNAL_MOUNT_FLAG, ++pkgId);
833 int res = unlink(mountFlag);
834 if (res == -1 && errno != ENOENT)
836 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
837 mountFlag, errno, strerror(errno));
841 memset(mountFlag, 0, _MAX_PATH_LENGTH);
842 sprintf(mountFlag, "%s/%s", _EXTERNAL_MOUNT_FLAG, pkgId);
843 res = unlink(mountFlag);
844 if (res == -1 && errno != ENOENT)
846 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
847 mountFlag, errno, strerror(errno));
851 SysLog(NID_IO, "[data_caging] FinalizeDataCaging() succeeded, appRootPath: %ls", appRootPath.GetPointer());
856 _FileImpl::GetAvailableUid(void)
862 _FileImpl::CreateOspApplicationDirectories(const String& appRootPath, const String& pkgId) // for 2.0 app
865 struct _OspDir appSubDir[] =
867 //{ "./shared\0", 0755, false },
868 //{ "./shared/data\0", 0755, true },
869 //{ "./shared/res\0", 0755, false },
870 //{ "./shared/trusted\0", 0755, true },
871 //{ "./cache\0", 0700, true }
876 result r = E_SUCCESS;
879 SysTryReturn(NID_IO, CleanDirectories(appRootPath, pkgId) == true, false, E_SYSTEM,
880 "[E_SYSTEM] Failed to clean directories for 2.0 application compatibility.");
883 unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
884 SysTryReturn(NID_IO, pAppRootPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
886 SysTryReturn(NID_IO, chdir(pAppRootPath.get()) == 0, false, E_SYSTEM,
887 "[E_SYSTEM] chdir() failed (%d, %s), path: %s", errno, strerror(errno), pAppRootPath.get());
889 uid = GetAvailableUid();
893 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); ++i)
895 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
896 if (ret == -1 && errno != 17) // EEXIST
898 SysLog(NID_IO, "[E_SYSTEM] mkdir() failed (%d, %s), path: %s, mode: 0%o",
899 errno, strerror(errno), appSubDir[i].path, appSubDir[i].mode);
903 if (appSubDir[i].appPrivilege)
905 ret = chown(appSubDir[i].path, uid, uid);
906 SysTryCatch(NID_IO, ret == 0, , E_SYSTEM,
907 "[E_SYSTEM] chown() failed (%d, %s), path: %s, uid: %d",
908 errno, strerror(errno), appSubDir[i].path, uid);
914 SysLog(NID_IO, "_FileImpl::CreateOspApplicationDirectories() succeeded.");
928 _FileImpl::CreateOspInternalDirectories(const String& appRootPath, const String& pkgId) // for 2.0 app
933 struct _OspDir appSubDir[] =
935 // { "./data", 0700, true }, // It is created by installer.
936 { "./shared", 0755, false },
937 { "./data/Share", 0000, true }, // mount from /opt/usr/share/.osp-compat/share/{pkgId}
938 { "./data/Share2", 0000, true }, // mount from /opt/usr/share/.osp-compat/share2/{pkgId}
939 { "./Share", 0000, false }, // mount from /opt/usr/share/.osp-compat/share
940 { "./Share2", 0000, false }, // mount from /opt/usr/share/.osp-compat/share2
941 // { "./Clipboard", 0000, false },
942 // { "./NPKI", 0000, false },
943 // { "./System", 0000, false },
944 // { "./Tmp", 0000, false },
945 { "./Media", 0000, false }, // mount from /opt/usr/media
946 { "./Storagecard", 0705, false },
947 { "./Storagecard/Media", 0000, false }, // mount from /opt/storage/sdcard
950 struct _OspDir mediaDir[] =
952 { "/opt/usr/media/Images", 0777, false },
953 { "/opt/usr/media/Sounds", 0777, false },
954 { "/opt/usr/media/Videos", 0777, false },
955 //{ "/opt/usr/media/Themes", 0777, false },
956 { "/opt/usr/media/Others", 0777, false }
959 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
960 String ospShareAppIdPath(L"share/");
961 String ospShare2AppIdPath(L"share2/");
962 result r = E_SUCCESS;
964 r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
965 SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM,
966 "[E_SYSTEM] String::Insert() failed. (error: %s)", GetErrorMessage(r));
968 r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
969 SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM,
970 "[E_SYSTEM] String::Insert() failed. (error: %s)", GetErrorMessage(r));
972 uid = GetAvailableUid();
974 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
976 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
977 if (ret == -1 && errno != 17) // EEXIST
979 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
980 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
983 if (appSubDir[i].appPrivilege)
985 ret = chown(appSubDir[i].path, uid, uid);
988 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
989 strerror(errno), appSubDir[i].path, uid);
995 ospShareAppIdPath.Append(pkgId);
996 unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
997 SysTryReturn(NID_IO, pOspShareAppIdPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
998 ret = mkdir(pOspShareAppIdPath.get(), 0705);
999 if (ret == -1 && errno != 17) // EEXIST
1001 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1002 strerror(errno), pOspShareAppIdPath.get(), 0705);
1005 ret = chown(pOspShareAppIdPath.get(), uid, uid);
1008 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1009 strerror(errno), pOspShareAppIdPath.get(), uid);
1013 ospShare2AppIdPath.Append(pkgId);
1014 unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
1015 SysTryReturn(NID_IO, pOspShare2AppIdPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
1016 ret = mkdir(pOspShare2AppIdPath.get(), 0705); // TODO: change to 0770
1017 if (ret == -1 && errno != 17) // EEXIST
1019 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1020 strerror(errno), pOspShare2AppIdPath.get(), 0705);
1023 ret = chown(pOspShare2AppIdPath.get(), uid, uid);
1026 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1027 strerror(errno), pOspShare2AppIdPath.get(), uid);
1032 for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); ++i)
1034 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
1035 if (ret == -1 && errno != 17) // EEXIST
1037 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1038 strerror(errno), mediaDir[i].path, mediaDir[i].mode);
1041 ret = chown(mediaDir[i].path, 5000, 5000);
1042 SysTryReturn(NID_IO, ret == 0, false, E_SYSTEM,
1043 "[E_SYSTEM] chown() failed (%d, %s), path: %s, uid: 5000, gid: 5000",
1044 errno, strerror(errno), mediaDir[i].path);
1048 // XXX: OSP compatible application's data packed in shared/data, shared/trusted directory of SDK
1049 // cannot be delivered.
1051 if (access("./shared/data", F_OK) == 0)
1053 char copyCmd[256] = { 0, };
1054 sprintf(copyCmd, "cp -rf ./shared/data/* /opt/usr/share/.osp-compat/share/%ls/", pkgId.GetPointer());
1055 ret = system(copyCmd);
1056 SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to copy command (%s)", copyCmd);
1058 SysTryReturn(NID_IO, system("rm -rf ./shared/data") != -1, false, E_SYSTEM,
1059 "[E_SYSTEM] rmdir() failed, path: ./shared/data");
1061 char chownCmd[256] = { 0, };
1062 sprintf(chownCmd, "chown -R 5000:5000 /opt/usr/share/.osp-compat/share/%ls/", pkgId.GetPointer());
1063 SysTryReturn(NID_IO, system(chownCmd) != -1, false, E_SYSTEM, "[E_SYSTEM] chown() failed");
1066 String appSharedDataPath(appRootPath);
1067 appSharedDataPath.Append(L"/shared/data");
1069 String appSharedTrustedPath(appRootPath);
1070 appSharedTrustedPath.Append(L"/shared/trusted");
1072 SysTryReturn(NID_IO, Directory::Remove(appSharedDataPath, true) == E_SUCCESS, false, E_SYSTEM,
1073 "[E_SYSTEM] Failed to remove path (%ls)", appSharedDataPath.GetPointer());
1074 SysTryReturn(NID_IO, Directory::Remove(appSharedTrustedPath, true) == E_SUCCESS, false, E_SYSTEM,
1075 "[E_SYSTEM] Failed to remove path (%ls)", appSharedTrustedPath.GetPointer());
1077 ret = symlink(pOspShareAppIdPath.get(), "./shared/data");
1078 SysTryReturn(NID_IO, ret == 0, false, E_SYSTEM,
1079 "[E_SYSTEM] symlink() failed, errno: %d (%s), link: ./shared/data -> %s",
1080 errno, strerror(errno), pOspShareAppIdPath.get());
1081 ret = symlink(pOspShare2AppIdPath.get(), "./shared/trusted");
1082 SysTryReturn(NID_IO, ret == 0, false, E_SYSTEM,
1083 "[E_SYSTEM] symlink() failed, errno: %d (%s), link: ./shared/trusted -> %s",
1084 errno, strerror(errno), pOspShare2AppIdPath.get());
1089 // TODO: Need to test this method.
1091 _FileImpl::CreateOspExternalDirectories(const String& pkgId)
1096 struct _OspDir appSubDir[] = { // virtual path
1097 // { "./data", 0700, true },
1098 { "./System", 0000, false }, // mount from /opt/apps/com.samsung.osp/system
1099 { "./Storagecard", 0705, false },
1100 { "./Storagecard/Media", 0000, false } // mount from /opt/storage/sdcard
1103 struct _OspDir mediaDir[] = { // physical path
1104 { "/opt/usr/media/Images", 0777, false },
1105 { "/opt/usr/media/Sounds", 0777, false },
1106 { "/opt/usr/media/Videos", 0777, false },
1107 //{ "/opt/usr/media/Themes", 0777, false },
1108 { "/opt/usr/media/Others", 0777, false }
1112 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
1114 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
1115 if (ret == -1 && errno != 17) // EEXIST
1117 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1118 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
1121 if (appSubDir[i].appPrivilege)
1123 ret = chown(appSubDir[i].path, uid, uid);
1126 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1127 strerror(errno), appSubDir[i].path, uid);
1134 for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); i++)
1136 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
1137 if (ret == -1 && errno != 17) // EEXIST
1139 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1140 strerror(errno), mediaDir[i].path, mediaDir[i].mode);
1150 _FileImpl::CreateSlpDirectories(void)
1154 struct _OspDir slpDir[] = { // virtual path
1155 //{ "./bin", 0000, false }, // mount from /bin
1156 //{ "./boot", 0000, false },
1157 //{ "./cache", 0000, false },
1158 { "./csa", 0000, false },
1159 { "./dev", 0000, false },
1160 { "./etc", 0000, false },
1161 { "./lib", 0000, false },
1162 //{ "./lost+found", 0000, false },
1163 { "./media", 0000, false },
1164 { "./mnt", 0000, false },
1165 { "./opt", 0000, false },
1166 //{ "./packaging", 0000, false },
1167 { "./proc", 0000, false },
1168 { "./sbin", 0000, false },
1169 { "./smack", 0000, false },
1170 { "./srv", 0000, false },
1171 { "./sys", 0000, false },
1172 { "./tmp", 0000, false },
1173 { "./usr", 0000, false },
1174 { "./var", 0000, false }
1177 for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
1179 ret = mkdir(slpDir[i].path, slpDir[i].mode);
1180 if (ret == -1 && errno != 17) // EEXIST
1182 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1183 strerror(errno), slpDir[i].path, slpDir[i].mode);
1192 _FileImpl::CreateSymbolicLink(void)
1194 struct _LinkDir linkDirList[] = {
1195 { "/opt/home", "./home" },
1196 { "/opt/home/root", "./root" },
1197 { "/mnt/mmc", "./sdcard" }
1200 for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
1202 int ret = symlink(linkDirList[i].srcPath, linkDirList[i].destPath);
1203 if (ret == -1 && errno != 17) // EEXIST
1205 SysLog(NID_IO, "Failed to create symbolic link, errno: %d (%s), src path: %s, dest path: %s",
1206 strerror(errno), linkDirList[i].srcPath, linkDirList[i].destPath);
1215 _FileImpl::VerifyFilePathCompatibility(const String& filePath, bool ospCompat)
1217 if (ospCompat == true)
1219 if (filePath[0] != L'/')
1224 int length = filePath.GetLength();
1233 _FileImpl::GetInstance(File& file)
1235 return file.__pFileImpl;
1239 _FileImpl::GetInstance(const File& file)
1241 return file.__pFileImpl;
1245 _FileImpl::ConvertVirtualToPhysicalPath(const String& virtualPath, String& physicalPath) // for 2.0 app
1247 SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(virtualPath, _AppInfo::IsOspCompat()) == true,
1248 E_INVALID_ARG, "[E_INVALID_ARG] %ls is not compatible.", virtualPath.GetPointer());
1250 const wchar_t* virtualPathPrefix[] =
1257 L"/Share/AppControl",
1264 L"/Storagecard/Media",
1265 //L"/Storagecard/NPKI",
1267 result r = E_SUCCESS;
1268 int count = sizeof(virtualPathPrefix)/sizeof(wchar_t*);
1271 for (i = 0; i < count; i++)
1273 SysLog(NID_IO, "[V2P] i: %d, path: %ls", i, virtualPathPrefix[i]);
1274 if (virtualPath.StartsWith(virtualPathPrefix[i], 0) == true)
1279 SysTryReturnResult(NID_IO, i != count, E_INVALID_ARG, "The path (%ls) is not matched.",
1280 virtualPath.GetPointer());
1282 int prefixLen = String(virtualPathPrefix[i]).GetLength();
1283 if (virtualPath.GetLength() > prefixLen)
1287 r = virtualPath.GetCharAt(prefixLen, ch);
1288 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
1289 GetErrorMessage(r), virtualPath.GetPointer());
1293 physicalPath.Clear();
1294 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1295 virtualPath.GetPointer());
1297 return E_INVALID_ARG;
1302 virtualPath.SubString(wcslen(virtualPathPrefix[i]), subPath);
1304 Tizen::App::App* pApp = Tizen::App::App::GetInstance();
1305 SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1306 String homePath = pApp->GetAppRootPath();
1307 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
1312 physicalPath = homePath + L"data/Share2";
1315 physicalPath = homePath + L"data/Share";
1318 physicalPath = homePath + L"data";
1321 physicalPath = homePath + L"res";
1324 physicalPath = ospCompatSharedPath + L"share2";
1327 physicalPath = ospCompatSharedPath + L"share/AppControl";
1330 physicalPath = ospCompatSharedPath + L"share";
1333 physicalPath = Tizen::System::Environment::GetMediaPath();
1336 physicalPath = Tizen::System::Environment::GetExternalStoragePath() + L"Media";
1339 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1340 virtualPath.GetPointer());
1341 return E_INVALID_ARG;
1344 if (subPath.IsEmpty() == false)
1346 physicalPath.Append(subPath);
1353 _FileImpl::ConvertPhysicalToVirtualPath(const String& physicalPath, String& virtualPath) // for 2.0 app
1355 result r = E_SUCCESS;
1356 const wchar_t* homeSubDir[] = {
1362 const wchar_t* ospHomeSubDir[] = {
1364 L"/share/AppControl",
1368 int homeSubDirCount = sizeof(homeSubDir)/sizeof(wchar_t*);
1369 int ospHomeSubDirCount = sizeof(ospHomeSubDir)/sizeof(wchar_t*);
1373 SysLog(NID_IO, "[P2V] physicalPath: %ls", physicalPath.GetPointer());
1375 Tizen::App::App* pApp = Tizen::App::App::GetInstance();
1376 SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1377 String homePath = pApp->GetAppRootPath();
1378 homePath.SetLength(homePath.GetLength() - 1);
1380 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
1381 ospCompatSharedPath.SetLength(ospCompatSharedPath.GetLength() - 1);
1383 String mediaPath = Tizen::System::Environment::GetMediaPath();
1384 mediaPath.SetLength(mediaPath.GetLength() - 1);
1386 String externalPath = Tizen::System::Environment::GetExternalStoragePath();
1387 externalPath.SetLength(externalPath.GetLength() - 1);
1389 if (physicalPath.StartsWith(homePath, 0) == true)
1391 physicalPath.SubString(homePath.GetLength(), subPath);
1393 for (i = 0; i < homeSubDirCount; i++)
1395 SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, homeSubDir[i]);
1396 if (subPath.StartsWith(homeSubDir[i], 0) == true)
1401 SysTryReturnResult(NID_IO, i != homeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1402 physicalPath.GetPointer());
1404 baseDirLen = homePath.GetLength() + String(homeSubDir[i]).GetLength();
1409 virtualPath = L"/Home/Share2";
1412 virtualPath = L"/Home/Share";
1415 virtualPath = L"/Home";
1418 virtualPath = L"/Res";
1425 else if (physicalPath.StartsWith(ospCompatSharedPath, 0) == true)
1427 physicalPath.SubString(ospCompatSharedPath.GetLength(), subPath);
1429 for (i = 0; i < ospHomeSubDirCount; i++)
1431 SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, ospHomeSubDir[i]);
1432 if (subPath.StartsWith(ospHomeSubDir[i], 0) == true)
1437 SysTryReturnResult(NID_IO, i != ospHomeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1438 physicalPath.GetPointer());
1440 baseDirLen = ospCompatSharedPath.GetLength() + String(ospHomeSubDir[i]).GetLength();
1445 virtualPath = L"/Share2";
1448 virtualPath = L"/Share/AppControl";
1451 virtualPath = L"/Share";
1457 else if (physicalPath.StartsWith(mediaPath, 0) == true)
1459 SysLog(NID_IO, "[P2V] media");
1460 virtualPath = L"/Media";
1461 baseDirLen = mediaPath.GetLength();
1463 else if (physicalPath.StartsWith(externalPath, 0) == true)
1465 SysLog(NID_IO, "[P2V] external media");
1466 virtualPath = L"/Storagecard/Media";
1467 baseDirLen = externalPath.GetLength();
1471 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1472 physicalPath.GetPointer());
1474 return E_INVALID_ARG;
1477 if (physicalPath.GetLength() > baseDirLen)
1481 r = physicalPath.GetCharAt(baseDirLen, ch);
1482 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
1483 GetErrorMessage(r), physicalPath.GetPointer());
1487 virtualPath.Clear();
1488 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1489 physicalPath.GetPointer());
1491 return E_INVALID_ARG;
1496 physicalPath.SubString(baseDirLen, subPath);
1498 if (subPath.IsEmpty() == false)
1500 virtualPath.Append(subPath);