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(), S_IRUSR | S_IWUSR | S_IXUSR);
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());
364 r = _NativeError::ConvertNativeErrorToResult(errno, true);
365 SysLog(NID_IO, "errno[%d], [%s] could not rename dirpath [%s].", errno, GetErrorMessage(r), pOldpath.get());
372 _DirectoryImpl::RemoveRecursively(char* pDirPath)
374 SysTryReturnResult(NID_IO, pDirPath != null, E_INVALID_ARG, "pDirPath is null.");
377 result r = E_SUCCESS;
379 pDir = opendir(pDirPath);
382 r = _NativeError::ConvertNativeErrorToResult(errno, true);
383 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath);
389 struct dirent dirEnt;
390 struct dirent* pDirEntResult = null;
391 char *pDirEntryName = null;
393 int ret = readdir_r(pDir, &dirEnt, &pDirEntResult);
396 r = _NativeError::ConvertNativeErrorToResult(errno, true);
397 SysLog(NID_IO, "[%s] Failed to read sub-directories. errno: %d (%s)",
398 GetErrorMessage(r), errno, strerror(errno));
402 // Remove all entries in dir. Delete the dir.
403 if (pDirEntResult == null)
405 ret = rmdir(pDirPath);
408 r = _NativeError::ConvertNativeErrorToResult(errno, true);
409 SysLog(NID_IO, "[%s] Failed to remove a directory. errno: %d (%s)",
410 GetErrorMessage(r), errno, strerror(errno));
412 goto CATCH; // both success and fail
415 pDirEntryName = &dirEnt.d_name[0];
418 if ((*pDirEntryName == '.' && *(pDirEntryName + 1) == 0x00) || (*pDirEntryName == '.' && *(pDirEntryName + 1) == '.' && *(pDirEntryName + 2) == 0x00))
423 // if the path name has '/' at the end remove it.
424 size_t len = strlen(pDirPath);
425 if (pDirPath[len - 1] == '/')
427 pDirPath[len - 1] = '\0';
430 // read_dir return relative path. Turn it to absolute
431 int parentDirLen = strlen(pDirPath);
432 int currEntryLen = strlen(dirEnt.d_name);
434 char absPath[parentDirLen + currEntryLen + 2]; // 2 - for '/' and '\0'
436 strcpy(absPath, pDirPath);
437 strcat(absPath, "/");
438 strcat(absPath, dirEnt.d_name);
439 //SysLog(NID_IO, "entry name: %s", absPath);
442 memset(&statbuf, 0, sizeof(struct stat));
443 if (lstat(absPath, &statbuf) == -1)
445 r = _NativeError::ConvertNativeErrorToResult(errno, true);
446 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
447 GetErrorMessage(r), errno, strerror(errno));
450 if (!S_ISLNK(statbuf.st_mode))
452 if (stat(absPath, &statbuf) < 0)
454 r = _NativeError::ConvertNativeErrorToResult(errno, true);
455 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
456 GetErrorMessage(r), errno, strerror(errno));
461 if (S_ISDIR(statbuf.st_mode))
463 r = _DirectoryImpl::RemoveRecursively(absPath);
471 ret = remove(absPath);
474 r = _NativeError::ConvertNativeErrorToResult(errno, true);
475 SysLog(NID_IO, "[%s] Failed to remove file (%s)", GetErrorMessage(r), absPath);
492 _DirectoryImpl::GetInstance(Directory& directory)
494 return directory.__pDirectoryImpl;
497 const _DirectoryImpl*
498 _DirectoryImpl::GetInstance(const Directory& directory)
500 return directory.__pDirectoryImpl;