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_DirectoryImpl.cpp
20 * @brief This is the implementation file for %_DirectoryImpl class.
31 #include <unique_ptr.h>
33 #include <FBaseResult.h>
34 #include <FAppPkgPackageInfo.h>
36 #include <FIoDirectory.h>
37 #include <FSysDeviceManager.h>
38 #include <FBaseSysLog.h>
40 #include <FBase_StringConverter.h>
41 #include <FBase_NativeError.h>
42 #include <FApp_AppInfo.h>
44 #include "FIo_FileImpl.h"
45 #include "FIo_DirectoryImpl.h"
46 #include "FIo_DirEnumeratorImpl.h"
49 using namespace Tizen::Base;
50 using namespace Tizen::App;
51 using namespace Tizen::System;
53 namespace Tizen { namespace Io
56 _DirectoryImpl::_DirectoryImpl(void)
61 _DirectoryImpl::~_DirectoryImpl(void)
67 if (closedir(static_cast <DIR*>(__pDir)) != 0)
69 r = _NativeError::ConvertNativeErrorToResult(errno, true);
70 SysLog(NID_IO, "[%s] Failed to close the file.", GetErrorMessage(r));
78 _DirectoryImpl::Construct(const String& dirPath)
82 SysAssertf(__pDir == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
84 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
85 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
87 unique_ptr<char[]> pDirPath(_StringConverter::CopyToCharArrayN(dirPath));
88 SysTryReturn(NID_IO, pDirPath != null, GetLastResult(), GetLastResult(),
89 "[%s] Invalid dir path.", GetErrorMessage(GetLastResult()));
91 __pDir = opendir(pDirPath.get());
94 r = _NativeError::ConvertNativeErrorToResult(errno, true);
95 SysSecureLogException(NID_IO, r, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath.get());
108 _DirectoryImpl::ReadN(void)
110 SysAssertf(__pDir != null, "Not yet constructed. Construct() should be called before use.\n");
112 unique_ptr<DirEnumerator> pDirEnum(_DirEnumeratorImpl::CreateDirEnumeratorInstanceN(__dirPath));
113 SysTryReturn(NID_IO, pDirEnum != null, null, E_OUT_OF_MEMORY,
114 "[E_OUT_OF_MEMORY] The memory is insufficient.");
116 return pDirEnum.release();
120 _DirectoryImpl::Create(const String& dirPath, bool createParentDirsToo)
122 result r = E_SUCCESS;
125 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
126 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
128 unique_ptr<char[]> pTempDirPath(_StringConverter::CopyToCharArrayN(dirPath));
129 SysTryReturn(NID_IO, pTempDirPath != null, GetLastResult(), GetLastResult(),
130 "[%s] Invalid dir path.", GetErrorMessage(GetLastResult()));
132 unique_ptr<char[]> pDirPath(new (std::nothrow) char[strlen(pTempDirPath.get()) + 2]);
133 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
135 strcpy(pDirPath.get(), pTempDirPath.get());
136 pDirPath[strlen(pTempDirPath.get())] = '/';
137 pDirPath[strlen(pTempDirPath.get()) + 1] = '\0';
139 // By the time we are here.. we assume we have a legal path to create
140 // the below logic works under the assumption that the path name does not end with '/'
141 ret = mkdir(pDirPath.get(), 0755);
144 // if parent directory does not exist and if we are asked to create them
145 if ((errno == ENOENT) && (createParentDirsToo == true))
147 // move till we find the directory which does not exist
148 char* pPos = pDirPath.get();
150 // if the dir path starts with '/', skip it
156 // scan for the next path seperator ie., '/'.
159 if (pPos && *pPos == '/')
162 if (access(pDirPath.get(), F_OK) != 0)
171 // found a dir which is not present and realDirPath has that name
174 ret = mkdir(pDirPath.get(), S_IRUSR | S_IWUSR | S_IXUSR);
175 if (ret == -1 && errno != EEXIST)
177 SysLog(NID_IO, "mkdir() failed. errno: %d (%s), path: %ls",
178 errno, strerror(errno), dirPath.GetPointer());
179 r = _NativeError::ConvertNativeErrorToResult(errno, true);
183 // find for the next dir path
186 while (pPos && *pPos == '/')
188 pPos++; // skip all occurances of consecutive '/' from current position
193 goto CATCH; // E_SUCCESS
196 pPos = strchr(pPos, '/');
203 goto CATCH; // E_SUCCESS
209 if (errno == ENAMETOOLONG)
215 r = _NativeError::ConvertNativeErrorToResult(errno, true);
217 SysLog(NID_IO, "[%s] Failed to create directory (%s) errno: %d (%s).",
218 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
230 _DirectoryImpl::Remove(const String& dirPath, bool recursive)
232 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
233 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
235 result r = E_SUCCESS;
237 if (_FileImpl::IsFileExist(dirPath) == false)
242 SysLog(NID_IO, "[E_FILE_NOT_FOUND] The directory path (%s) does not exist.", dirPath.GetPointer());
243 r = E_FILE_NOT_FOUND;
247 SysPropagate(NID_IO, r);
252 unique_ptr<char[]> pDirPath(_StringConverter::CopyToCharArrayN(dirPath));
253 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
255 char resolvedPath[PATH_MAX] = {0,};
256 if (realpath(pDirPath.get(), resolvedPath) == null)
261 r = E_ILLEGAL_ACCESS;
276 r = E_FILE_NOT_FOUND;
283 SysLog(NID_IO, "[%s] Failed to produce canonical absolute path (%ls). errno: %d (%s)",
284 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
289 int ret = rmdir(resolvedPath);
297 r = E_ILLEGAL_ACCESS;
309 r = E_FILE_NOT_FOUND;
317 r = RemoveRecursively(resolvedPath);
321 r = E_FILE_ALREADY_EXIST;
330 SysLog(NID_IO, "[%s] Failed to remove the directory path (%ls). errno: %d (%s)",
331 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
339 _DirectoryImpl::Rename(const String& orgDirPath, const String& newDirPath)
341 result r = E_SUCCESS;
344 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(orgDirPath, _AppInfo::IsOspCompat()) == true,
345 E_INVALID_ARG, " [%ls] is not compatible.", orgDirPath.GetPointer());
346 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(newDirPath, _AppInfo::IsOspCompat()) == true,
347 E_INVALID_ARG, " [%ls] is not compatible.", newDirPath.GetPointer());
349 if (_FileImpl::IsFileExist(newDirPath))
351 return E_FILE_ALREADY_EXIST;
354 unique_ptr<char[]> pOldpath(_StringConverter::CopyToCharArrayN(orgDirPath));
355 SysTryReturn(NID_IO, (null != pOldpath), GetLastResult(), GetLastResult(), "[%s] Invalid old file path.", GetErrorMessage(GetLastResult()));
357 unique_ptr<char[]> pNewpath(_StringConverter::CopyToCharArrayN(newDirPath));
358 SysTryReturn(NID_IO, (null != pNewpath), GetLastResult(), GetLastResult(), "[%s] Invalid new file path.", GetErrorMessage(GetLastResult()));
360 ret = rename(pOldpath.get(), pNewpath.get());
371 r = E_FILE_ALREADY_EXIST;
377 r = _NativeError::ConvertNativeErrorToResult(errno, true);
380 SysLogException(NID_IO, r, "[%s] Renaming the directory path (%s) is failed, errno: %d (%s)", GetErrorMessage(r), pOldpath.get(), errno, strerror(errno));
387 _DirectoryImpl::RemoveRecursively(char* pDirPath)
389 SysTryReturnResult(NID_IO, pDirPath != null, E_INVALID_ARG, "pDirPath is null.");
392 result r = E_SUCCESS;
394 pDir = opendir(pDirPath);
397 r = _NativeError::ConvertNativeErrorToResult(errno, true);
398 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath);
404 struct dirent dirEnt;
405 struct dirent* pDirEntResult = null;
406 char *pDirEntryName = null;
408 int ret = readdir_r(pDir, &dirEnt, &pDirEntResult);
411 r = _NativeError::ConvertNativeErrorToResult(errno, true);
412 SysLog(NID_IO, "[%s] Failed to read sub-directories. errno: %d (%s)",
413 GetErrorMessage(r), errno, strerror(errno));
417 // Remove all entries in dir. Delete the dir.
418 if (pDirEntResult == null)
420 ret = rmdir(pDirPath);
423 r = _NativeError::ConvertNativeErrorToResult(errno, true);
424 SysLog(NID_IO, "[%s] Failed to remove a directory. errno: %d (%s)",
425 GetErrorMessage(r), errno, strerror(errno));
427 goto CATCH; // both success and fail
430 pDirEntryName = &dirEnt.d_name[0];
433 if ((*pDirEntryName == '.' && *(pDirEntryName + 1) == 0x00) || (*pDirEntryName == '.' && *(pDirEntryName + 1) == '.' && *(pDirEntryName + 2) == 0x00))
438 // if the path name has '/' at the end remove it.
439 size_t len = strlen(pDirPath);
440 if (pDirPath[len - 1] == '/')
442 pDirPath[len - 1] = '\0';
445 // read_dir return relative path. Turn it to absolute
446 int parentDirLen = strlen(pDirPath);
447 int currEntryLen = strlen(dirEnt.d_name);
449 char absPath[parentDirLen + currEntryLen + 2]; // 2 - for '/' and '\0'
451 strcpy(absPath, pDirPath);
452 strcat(absPath, "/");
453 strcat(absPath, dirEnt.d_name);
455 struct stat64 statbuf;
456 memset(&statbuf, 0, sizeof(struct stat64));
457 if (lstat64(absPath, &statbuf) == -1)
459 r = _NativeError::ConvertNativeErrorToResult(errno, true);
460 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
461 GetErrorMessage(r), errno, strerror(errno));
464 if (!S_ISLNK(statbuf.st_mode))
466 if (stat64(absPath, &statbuf) < 0)
468 r = _NativeError::ConvertNativeErrorToResult(errno, true);
469 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
470 GetErrorMessage(r), errno, strerror(errno));
475 if (S_ISDIR(statbuf.st_mode))
477 r = _DirectoryImpl::RemoveRecursively(absPath);
485 ret = remove(absPath);
488 r = _NativeError::ConvertNativeErrorToResult(errno, true);
489 SysLog(NID_IO, "[%s] Failed to remove file (%s)", GetErrorMessage(r), absPath);
506 _DirectoryImpl::GetInstance(Directory& directory)
508 return directory.__pDirectoryImpl;
511 const _DirectoryImpl*
512 _DirectoryImpl::GetInstance(const Directory& directory)
514 return directory.__pDirectoryImpl;