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 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath.get());
109 _DirectoryImpl::ReadN(void)
111 SysAssertf(__pDir != null, "Not yet constructed. Construct() should be called before use.\n");
113 unique_ptr<DirEnumerator> pDirEnum(_DirEnumeratorImpl::CreateDirEnumeratorInstanceN(__dirPath));
114 SysTryReturn(NID_IO, pDirEnum != null, null, E_OUT_OF_MEMORY,
115 "[E_OUT_OF_MEMORY] The memory is insufficient.");
117 return pDirEnum.release();
121 _DirectoryImpl::Create(const String& dirPath, bool createParentDirsToo)
123 result r = E_SUCCESS;
126 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
127 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
129 unique_ptr<char[]> pTempDirPath(_StringConverter::CopyToCharArrayN(dirPath));
130 SysTryReturn(NID_IO, pTempDirPath != null, GetLastResult(), GetLastResult(),
131 "[%s] Invalid dir path.", GetErrorMessage(GetLastResult()));
133 unique_ptr<char[]> pDirPath(new (std::nothrow) char[strlen(pTempDirPath.get()) + 2]);
134 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
136 strcpy(pDirPath.get(), pTempDirPath.get());
137 pDirPath[strlen(pTempDirPath.get())] = '/';
138 pDirPath[strlen(pTempDirPath.get()) + 1] = '\0';
140 // By the time we are here.. we assume we have a legal path to create
141 // the below logic works under the assumption that the path name does not end with '/'
142 ret = mkdir(pDirPath.get(), 0755);
145 // if parent directory does not exist and if we are asked to create them
146 if ((errno == ENOENT) && (createParentDirsToo == true))
148 // move till we find the directory which does not exist
149 char* pPos = pDirPath.get();
151 // if the dir path starts with '/', skip it
157 // scan for the next path seperator ie., '/'.
160 if (pPos && *pPos == '/')
163 if (access(pDirPath.get(), F_OK) != 0)
172 // found a dir which is not present and realDirPath has that name
175 ret = mkdir(pDirPath.get(), S_IRUSR | S_IWUSR | S_IXUSR);
176 if (ret == -1 && errno != EEXIST)
178 SysLog(NID_IO, "mkdir() failed. errno: %d (%s), path: %ls",
179 errno, strerror(errno), dirPath.GetPointer());
180 r = _NativeError::ConvertNativeErrorToResult(errno, true);
184 // find for the next dir path
187 while (pPos && *pPos == '/')
189 pPos++; // skip all occurances of consecutive '/' from current position
194 goto CATCH; // E_SUCCESS
197 pPos = strchr(pPos, '/');
204 goto CATCH; // E_SUCCESS
210 if (errno == ENAMETOOLONG)
216 r = _NativeError::ConvertNativeErrorToResult(errno, true);
218 SysLog(NID_IO, "[%s] Failed to create directory (%s) errno: %d (%s).",
219 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
231 _DirectoryImpl::Remove(const String& dirPath, bool recursive)
233 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
234 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
236 result r = E_SUCCESS;
238 if (_FileImpl::IsFileExist(dirPath) == false)
243 SysLog(NID_IO, "[E_FILE_NOT_FOUND] The directory path (%s) does not exist.", dirPath.GetPointer());
244 r = E_FILE_NOT_FOUND;
248 SysPropagate(NID_IO, r);
253 unique_ptr<char[]> pDirPath(_StringConverter::CopyToCharArrayN(dirPath));
254 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
256 char resolvedPath[PATH_MAX] = {0,};
257 if (realpath(pDirPath.get(), resolvedPath) == null)
262 r = E_ILLEGAL_ACCESS;
277 r = E_FILE_NOT_FOUND;
284 SysLog(NID_IO, "[%s] Failed to produce canonical absolute path (%ls). errno: %d (%s)",
285 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
290 int ret = rmdir(resolvedPath);
298 r = E_ILLEGAL_ACCESS;
310 r = E_FILE_NOT_FOUND;
318 r = RemoveRecursively(resolvedPath);
322 r = E_FILE_ALREADY_EXIST;
331 SysLog(NID_IO, "[%s] Failed to remove the directory path (%ls). errno: %d (%s)",
332 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
340 _DirectoryImpl::Rename(const String& orgDirPath, const String& newDirPath)
342 result r = E_SUCCESS;
345 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(orgDirPath, _AppInfo::IsOspCompat()) == true,
346 E_INVALID_ARG, " [%ls] is not compatible.", orgDirPath.GetPointer());
347 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(newDirPath, _AppInfo::IsOspCompat()) == true,
348 E_INVALID_ARG, " [%ls] is not compatible.", newDirPath.GetPointer());
350 if (_FileImpl::IsFileExist(newDirPath))
352 return E_FILE_ALREADY_EXIST;
355 unique_ptr<char[]> pOldpath(_StringConverter::CopyToCharArrayN(orgDirPath));
356 SysTryReturn(NID_IO, (null != pOldpath), GetLastResult(), GetLastResult(), "[%s] Invalid old file path.", GetErrorMessage(GetLastResult()));
358 unique_ptr<char[]> pNewpath(_StringConverter::CopyToCharArrayN(newDirPath));
359 SysTryReturn(NID_IO, (null != pNewpath), GetLastResult(), GetLastResult(), "[%s] Invalid new file path.", GetErrorMessage(GetLastResult()));
361 ret = rename(pOldpath.get(), pNewpath.get());
372 r = E_FILE_ALREADY_EXIST;
378 r = _NativeError::ConvertNativeErrorToResult(errno, true);
381 SysLogException(NID_IO, r, "[%s] Renaming the directory path (%s) is failed, errno: %d (%s)", GetErrorMessage(r), pOldpath.get(), errno, strerror(errno));
388 _DirectoryImpl::RemoveRecursively(char* pDirPath)
390 SysTryReturnResult(NID_IO, pDirPath != null, E_INVALID_ARG, "pDirPath is null.");
393 result r = E_SUCCESS;
395 pDir = opendir(pDirPath);
398 r = _NativeError::ConvertNativeErrorToResult(errno, true);
399 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath);
405 struct dirent dirEnt;
406 struct dirent* pDirEntResult = null;
407 char *pDirEntryName = null;
409 int ret = readdir_r(pDir, &dirEnt, &pDirEntResult);
412 r = _NativeError::ConvertNativeErrorToResult(errno, true);
413 SysLog(NID_IO, "[%s] Failed to read sub-directories. errno: %d (%s)",
414 GetErrorMessage(r), errno, strerror(errno));
418 // Remove all entries in dir. Delete the dir.
419 if (pDirEntResult == null)
421 ret = rmdir(pDirPath);
424 r = _NativeError::ConvertNativeErrorToResult(errno, true);
425 SysLog(NID_IO, "[%s] Failed to remove a directory. errno: %d (%s)",
426 GetErrorMessage(r), errno, strerror(errno));
428 goto CATCH; // both success and fail
431 pDirEntryName = &dirEnt.d_name[0];
434 if ((*pDirEntryName == '.' && *(pDirEntryName + 1) == 0x00) || (*pDirEntryName == '.' && *(pDirEntryName + 1) == '.' && *(pDirEntryName + 2) == 0x00))
439 // if the path name has '/' at the end remove it.
440 size_t len = strlen(pDirPath);
441 if (pDirPath[len - 1] == '/')
443 pDirPath[len - 1] = '\0';
446 // read_dir return relative path. Turn it to absolute
447 int parentDirLen = strlen(pDirPath);
448 int currEntryLen = strlen(dirEnt.d_name);
450 char absPath[parentDirLen + currEntryLen + 2]; // 2 - for '/' and '\0'
452 strcpy(absPath, pDirPath);
453 strcat(absPath, "/");
454 strcat(absPath, dirEnt.d_name);
455 //SysLog(NID_IO, "entry name: %s", absPath);
458 memset(&statbuf, 0, sizeof(struct stat));
459 if (lstat(absPath, &statbuf) == -1)
461 r = _NativeError::ConvertNativeErrorToResult(errno, true);
462 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
463 GetErrorMessage(r), errno, strerror(errno));
466 if (!S_ISLNK(statbuf.st_mode))
468 if (stat(absPath, &statbuf) < 0)
470 r = _NativeError::ConvertNativeErrorToResult(errno, true);
471 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
472 GetErrorMessage(r), errno, strerror(errno));
477 if (S_ISDIR(statbuf.st_mode))
479 r = _DirectoryImpl::RemoveRecursively(absPath);
487 ret = remove(absPath);
490 r = _NativeError::ConvertNativeErrorToResult(errno, true);
491 SysLog(NID_IO, "[%s] Failed to remove file (%s)", GetErrorMessage(r), absPath);
508 _DirectoryImpl::GetInstance(Directory& directory)
510 return directory.__pDirectoryImpl;
513 const _DirectoryImpl*
514 _DirectoryImpl::GetInstance(const Directory& directory)
516 return directory.__pDirectoryImpl;