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_DirectoryImpl.cpp
19 * @brief This is the implementation file for %_DirectoryImpl class.
30 #include <unique_ptr.h>
32 #include <FBaseResult.h>
33 #include <FAppPkgPackageInfo.h>
35 #include <FIoDirectory.h>
36 #include <FSysDeviceManager.h>
37 #include <FBaseSysLog.h>
39 #include <FBase_StringConverter.h>
40 #include <FBase_NativeError.h>
41 #include <FApp_AppInfo.h>
43 #include "FIo_FileImpl.h"
44 #include "FIo_DirectoryImpl.h"
45 #include "FIo_DirEnumeratorImpl.h"
48 using namespace Tizen::Base;
49 using namespace Tizen::App;
50 using namespace Tizen::System;
52 namespace Tizen { namespace Io
55 _DirectoryImpl::_DirectoryImpl(void)
60 _DirectoryImpl::~_DirectoryImpl(void)
66 if (closedir(static_cast <DIR*>(__pDir)) != 0)
68 r = _NativeError::ConvertNativeErrorToResult(errno, true);
69 SysLog(NID_IO, "[%s] Failed to close the file.", GetErrorMessage(r));
77 _DirectoryImpl::Construct(const String& dirPath)
81 SysAssertf(__pDir == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
83 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
84 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
86 unique_ptr<char[]> pDirPath(_StringConverter::CopyToCharArrayN(dirPath));
87 SysTryReturn(NID_IO, pDirPath != null, GetLastResult(), GetLastResult(),
88 "[%s] Invalid dir path.", GetErrorMessage(GetLastResult()));
90 __pDir = opendir(pDirPath.get());
93 r = _NativeError::ConvertNativeErrorToResult(errno, true);
94 SysSecureLogException(NID_IO, r, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath.get());
107 _DirectoryImpl::ReadN(void)
109 SysAssertf(__pDir != null, "Not yet constructed. Construct() should be called before use.\n");
111 unique_ptr<DirEnumerator> pDirEnum(_DirEnumeratorImpl::CreateDirEnumeratorInstanceN(__dirPath));
112 SysTryReturn(NID_IO, pDirEnum != null, null, E_OUT_OF_MEMORY,
113 "[E_OUT_OF_MEMORY] The memory is insufficient.");
115 return pDirEnum.release();
119 _DirectoryImpl::Create(const String& dirPath, bool createParentDirsToo)
121 result r = E_SUCCESS;
124 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
125 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
127 unique_ptr<char[]> pTempDirPath(_StringConverter::CopyToCharArrayN(dirPath));
128 SysTryReturn(NID_IO, pTempDirPath != null, GetLastResult(), GetLastResult(),
129 "[%s] Invalid dir path.", GetErrorMessage(GetLastResult()));
131 unique_ptr<char[]> pDirPath(new (std::nothrow) char[strlen(pTempDirPath.get()) + 2]);
132 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
134 strcpy(pDirPath.get(), pTempDirPath.get());
135 pDirPath[strlen(pTempDirPath.get())] = '/';
136 pDirPath[strlen(pTempDirPath.get()) + 1] = '\0';
138 // By the time we are here.. we assume we have a legal path to create
139 // the below logic works under the assumption that the path name does not end with '/'
140 ret = mkdir(pDirPath.get(), 0755);
143 // if parent directory does not exist and if we are asked to create them
144 if ((errno == ENOENT) && (createParentDirsToo == true))
146 // move till we find the directory which does not exist
147 char* pPos = pDirPath.get();
149 // if the dir path starts with '/', skip it
155 // scan for the next path seperator ie., '/'.
158 if (pPos && *pPos == '/')
161 if (access(pDirPath.get(), F_OK) != 0)
170 // found a dir which is not present and realDirPath has that name
173 ret = mkdir(pDirPath.get(), S_IRUSR | S_IWUSR | S_IXUSR);
174 if (ret == -1 && errno != EEXIST)
176 SysLog(NID_IO, "mkdir() failed. errno: %d (%s), path: %ls",
177 errno, strerror(errno), dirPath.GetPointer());
178 r = _NativeError::ConvertNativeErrorToResult(errno, true);
182 // find for the next dir path
185 while (pPos && *pPos == '/')
187 pPos++; // skip all occurances of consecutive '/' from current position
192 goto CATCH; // E_SUCCESS
195 pPos = strchr(pPos, '/');
202 goto CATCH; // E_SUCCESS
208 if (errno == ENAMETOOLONG)
214 r = _NativeError::ConvertNativeErrorToResult(errno, true);
216 SysLog(NID_IO, "[%s] Failed to create directory (%s) errno: %d (%s).",
217 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
229 _DirectoryImpl::Remove(const String& dirPath, bool recursive)
231 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(dirPath, _AppInfo::IsOspCompat()) == true,
232 E_INVALID_ARG, " [%ls] is not compatible.", dirPath.GetPointer());
234 result r = E_SUCCESS;
236 if (_FileImpl::IsFileExist(dirPath) == false)
241 SysLog(NID_IO, "[E_FILE_NOT_FOUND] The directory path (%s) does not exist.", dirPath.GetPointer());
242 r = E_FILE_NOT_FOUND;
246 SysPropagate(NID_IO, r);
251 unique_ptr<char[]> pDirPath(_StringConverter::CopyToCharArrayN(dirPath));
252 SysTryReturnResult(NID_IO, pDirPath != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
254 char resolvedPath[PATH_MAX] = {0,};
255 if (realpath(pDirPath.get(), resolvedPath) == null)
260 r = E_ILLEGAL_ACCESS;
275 r = E_FILE_NOT_FOUND;
282 SysLog(NID_IO, "[%s] Failed to produce canonical absolute path (%ls). errno: %d (%s)",
283 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
288 int ret = rmdir(resolvedPath);
296 r = E_ILLEGAL_ACCESS;
308 r = E_FILE_NOT_FOUND;
316 r = RemoveRecursively(resolvedPath);
320 r = E_FILE_ALREADY_EXIST;
329 SysLog(NID_IO, "[%s] Failed to remove the directory path (%ls). errno: %d (%s)",
330 GetErrorMessage(r), dirPath.GetPointer(), errno, strerror(errno));
338 _DirectoryImpl::Rename(const String& orgDirPath, const String& newDirPath)
340 result r = E_SUCCESS;
343 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(orgDirPath, _AppInfo::IsOspCompat()) == true,
344 E_INVALID_ARG, " [%ls] is not compatible.", orgDirPath.GetPointer());
345 SysTryReturnResult(NID_IO, _FileImpl::VerifyFilePathCompatibility(newDirPath, _AppInfo::IsOspCompat()) == true,
346 E_INVALID_ARG, " [%ls] is not compatible.", newDirPath.GetPointer());
348 if (_FileImpl::IsFileExist(newDirPath))
350 return E_FILE_ALREADY_EXIST;
353 unique_ptr<char[]> pOldpath(_StringConverter::CopyToCharArrayN(orgDirPath));
354 SysTryReturn(NID_IO, (null != pOldpath), GetLastResult(), GetLastResult(), "[%s] Invalid old file path.", GetErrorMessage(GetLastResult()));
356 unique_ptr<char[]> pNewpath(_StringConverter::CopyToCharArrayN(newDirPath));
357 SysTryReturn(NID_IO, (null != pNewpath), GetLastResult(), GetLastResult(), "[%s] Invalid new file path.", GetErrorMessage(GetLastResult()));
359 ret = rename(pOldpath.get(), pNewpath.get());
370 r = E_FILE_ALREADY_EXIST;
376 r = _NativeError::ConvertNativeErrorToResult(errno, true);
379 SysLogException(NID_IO, r, "[%s] Renaming the directory path (%s) is failed, errno: %d (%s)", GetErrorMessage(r), pOldpath.get(), errno, strerror(errno));
386 _DirectoryImpl::RemoveRecursively(char* pDirPath)
388 SysTryReturnResult(NID_IO, pDirPath != null, E_INVALID_ARG, "pDirPath is null.");
391 result r = E_SUCCESS;
393 pDir = opendir(pDirPath);
396 r = _NativeError::ConvertNativeErrorToResult(errno, true);
397 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPath);
403 struct dirent dirEnt;
404 struct dirent* pDirEntResult = null;
405 char *pDirEntryName = null;
407 int ret = readdir_r(pDir, &dirEnt, &pDirEntResult);
410 r = _NativeError::ConvertNativeErrorToResult(errno, true);
411 SysLog(NID_IO, "[%s] Failed to read sub-directories. errno: %d (%s)",
412 GetErrorMessage(r), errno, strerror(errno));
416 // Remove all entries in dir. Delete the dir.
417 if (pDirEntResult == null)
419 ret = rmdir(pDirPath);
422 r = _NativeError::ConvertNativeErrorToResult(errno, true);
423 SysLog(NID_IO, "[%s] Failed to remove a directory. errno: %d (%s)",
424 GetErrorMessage(r), errno, strerror(errno));
426 goto CATCH; // both success and fail
429 pDirEntryName = &dirEnt.d_name[0];
432 if ((*pDirEntryName == '.' && *(pDirEntryName + 1) == 0x00) || (*pDirEntryName == '.' && *(pDirEntryName + 1) == '.' && *(pDirEntryName + 2) == 0x00))
437 // if the path name has '/' at the end remove it.
438 size_t len = strlen(pDirPath);
439 if (pDirPath[len - 1] == '/')
441 pDirPath[len - 1] = '\0';
444 // read_dir return relative path. Turn it to absolute
445 int parentDirLen = strlen(pDirPath);
446 int currEntryLen = strlen(dirEnt.d_name);
448 char absPath[parentDirLen + currEntryLen + 2]; // 2 - for '/' and '\0'
450 strcpy(absPath, pDirPath);
451 strcat(absPath, "/");
452 strcat(absPath, dirEnt.d_name);
454 struct stat64 statbuf;
455 memset(&statbuf, 0, sizeof(struct stat64));
456 if (lstat64(absPath, &statbuf) == -1)
458 r = _NativeError::ConvertNativeErrorToResult(errno, true);
459 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
460 GetErrorMessage(r), errno, strerror(errno));
463 if (!S_ISLNK(statbuf.st_mode))
465 if (stat64(absPath, &statbuf) < 0)
467 r = _NativeError::ConvertNativeErrorToResult(errno, true);
468 SysLog(NID_IO, "[%s] Failed to get file status. errno: %d (%s)",
469 GetErrorMessage(r), errno, strerror(errno));
474 if (S_ISDIR(statbuf.st_mode))
476 r = _DirectoryImpl::RemoveRecursively(absPath);
484 ret = remove(absPath);
487 r = _NativeError::ConvertNativeErrorToResult(errno, true);
488 SysLog(NID_IO, "[%s] Failed to remove file (%s)", GetErrorMessage(r), absPath);
505 _DirectoryImpl::GetInstance(Directory& directory)
507 return directory.__pDirectoryImpl;
510 const _DirectoryImpl*
511 _DirectoryImpl::GetInstance(const Directory& directory)
513 return directory.__pDirectoryImpl;