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_DirEnumeratorImpl.cpp
20 * @brief This is the implementation file for _DirEnumeratorImpl class.
29 #include <unique_ptr.h>
31 #include <FBaseDateTime.h>
32 #include <FIoDirEntry.h>
33 #include <FIoDirEnumerator.h>
34 #include <FBaseSysLog.h>
36 #include <FBase_NativeError.h>
37 #include <FBase_StringConverter.h>
38 #include <FIo_DirEnumeratorImpl.h>
39 #include <FIo_DirEntryImpl.h>
42 using namespace Tizen::Base;
44 namespace Tizen { namespace Io
47 static const int _BASE_YEAR = 1900;
49 _DirEnumeratorImpl::_DirEnumeratorImpl(const String& dirPath)
50 : __validAccess(false)
51 , __pFileFindInfo(null)
52 , __pCurDirEntry(null)
55 __absoluteDirPath = dirPath;
58 _DirEnumeratorImpl::_DirEnumeratorImpl(const _DirEnumeratorImpl& dirEnumeratorImpl)
59 : __validAccess(false)
60 , __pFileFindInfo(null)
61 , __pCurDirEntry(null)
63 SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This copy constructor is not implemented.");
64 SetLastResult(E_UNSUPPORTED_OPERATION);
68 _DirEnumeratorImpl::operator =(const _DirEnumeratorImpl& dirEnumeratorImpl)
70 if (this != &dirEnumeratorImpl)
72 SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This assign operator is not implemented.");
73 SetLastResult(E_UNSUPPORTED_OPERATION);
78 _DirEnumeratorImpl::~_DirEnumeratorImpl(void)
82 closedir(static_cast <DIR*>(__pFileFindInfo));
83 __pFileFindInfo = null;
86 delete __pCurDirEntry;
90 _DirEnumeratorImpl::GetCurrentDirEntry(void) const
94 unique_ptr<DirEntry> pDirEntry(_DirEntryImpl::CreateDirEntryInstanceN());
95 DirEntry dirEntryObject = *pDirEntry;
97 SysTryReturn(NID_IO, __pCurDirEntry != null, dirEntryObject, E_INVALID_STATE,
98 "[E_INVALID_STATE] Instance has not been created yet.");
100 _DirEntryImpl::GetInstance(&dirEntryObject)->Set(__pCurDirEntry->GetDateTime(),
101 __pCurDirEntry->GetFileSize(), __pCurDirEntry->GetName(), __pCurDirEntry->IsDirectory(),
102 __pCurDirEntry->IsReadOnly(), __pCurDirEntry->IsHidden());
105 return dirEntryObject;
109 _DirEnumeratorImpl::GetCurrent(void) const
111 SetLastResult(E_SUCCESS);
112 return __pCurDirEntry;
116 _DirEnumeratorImpl::MoveNext(void)
118 result r = E_SUCCESS;
119 struct dirent dirEnt;
120 struct dirent* pDirEntResult = null;
121 struct stat64 statbuf;
122 struct tm* pTm = null;
127 char* pDirEntryName = null;
129 SysTryReturnResult(NID_IO, __validAccess == true, E_ILLEGAL_ACCESS,
130 "Given path cannot be accessed!");
131 SysTryReturnResult(NID_IO, __absoluteDirPath.GetLength() > 0 && __absoluteDirPath.GetLength() <= PATH_MAX,
132 E_INVALID_ARG, "Invalid argument was passed. Given pattern length is not correct!");
134 unique_ptr<char[]> pAbsDirPath(_StringConverter::CopyToCharArrayN(String(__absoluteDirPath)));
135 SysTryReturn(NID_IO, (pAbsDirPath != null), GetLastResult(), GetLastResult(),
136 "[%s] Invalid argument was passed. Given pattern length is not correct!", GetErrorMessage(GetLastResult()));
138 if (__pFileFindInfo == null)
140 __pFileFindInfo = opendir(pAbsDirPath.get());
141 if (__pFileFindInfo == null)
143 r = _NativeError::ConvertNativeErrorToResult(errno, true);
144 SysLog(NID_IO, "[%s] Failed to open directory (%s), [%s].", GetErrorMessage(r),
145 GetErrorMessage((result) E_FILE_NOT_FOUND), pAbsDirPath.get());
151 // move to next entry in the directory
153 ret = readdir_r((DIR*) __pFileFindInfo, &dirEnt, &pDirEntResult);
154 SysTryReturn(NID_IO, (ret == 0), __ConvertNativeErrorToResult(errno),
155 __ConvertNativeErrorToResult(errno), "[%s] Failed to read next dir entry.", __ConvertNativeErrorToMessage(errno));
157 if (pDirEntResult == null)
159 return E_END_OF_FILE; // Complete reading the directory
162 //if (dirEnt.d_name[0] == '.')
167 // prepare entry path
168 dirEntryPath.Append(__absoluteDirPath);
169 dirEntryPath.Append(L"/");
170 dirEntryPath.Append(dirEnt.d_name);
171 unique_ptr<char[]> pAbsDirEntryPath(_StringConverter::CopyToCharArrayN(dirEntryPath));
172 SysTryReturn(NID_IO, (pAbsDirEntryPath != null), GetLastResult(), GetLastResult(),
173 "[%s] Invalid argument was passed. Given pattern length is not correct!", GetErrorMessage(GetLastResult()));
176 ret = stat64(pAbsDirEntryPath.get(), &statbuf);
177 SysTryReturn(NID_IO, (ret == 0), r = __ConvertNativeErrorToResult(errno), __ConvertNativeErrorToResult(errno),
178 "[%s] Failed to get attributes for dir entry (%s) whose absolute dirpath is (%s)with errno [%d].",
179 __ConvertNativeErrorToMessage(errno), dirEnt.d_name, pAbsDirPath.get(), errno);
181 pTm = localtime(&statbuf.st_mtime);
182 SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
183 r = dateTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
184 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
186 if (__pCurDirEntry == null)
188 __pCurDirEntry = _DirEntryImpl::CreateDirEntryInstanceN();
189 SysTryReturnResult(NID_IO, __pCurDirEntry != null, E_OUT_OF_MEMORY,
190 "DirEntry allocation failed.");
193 pDirEntryName = &dirEnt.d_name[0];
195 // check for a hidden file/directory including . and ..
196 if (dirEnt.d_name[0] == '.')
201 _DirEntryImpl::GetInstance(__pCurDirEntry)->Set(dateTime, statbuf.st_size, String(dirEnt.d_name),
202 S_ISDIR(statbuf.st_mode), (statbuf.st_mode & S_IWUSR) ? false : true, hidden);
208 _DirEnumeratorImpl::Reset(void)
210 result r = E_SUCCESS;
214 delete __pCurDirEntry;
215 __pCurDirEntry = null;
218 // close and reopen the dir
221 closedir(static_cast <DIR*>(__pFileFindInfo));
224 unique_ptr<char[]> pDirPathName(_StringConverter::CopyToCharArrayN(__absoluteDirPath));
225 SysTryReturn(NID_IO, pDirPathName != null, GetLastResult(), GetLastResult(),
226 "[%s] Failed to close file.", GetErrorMessage(GetLastResult()));
228 __pFileFindInfo = opendir(pDirPathName.get());
229 if (__pFileFindInfo == null)
231 r = __ConvertNativeErrorToResult(errno);
232 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPathName.get());
239 _DirEnumeratorImpl::GetInstance(DirEnumerator& dirEnumerator)
241 return dirEnumerator.__pDirEnumeratorImpl;
244 const _DirEnumeratorImpl*
245 _DirEnumeratorImpl::GetInstance(const DirEnumerator& dirEnumerator)
247 return dirEnumerator.__pDirEnumeratorImpl;
251 _DirEnumeratorImpl::CreateDirEnumeratorInstanceN(const String& dirPath)
253 unique_ptr<DirEnumerator> pDirEnumerator(new (std::nothrow) DirEnumerator(dirPath));
254 SysTryReturn(NID_IO, pDirEnumerator != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
255 return pDirEnumerator.release();