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;
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 = stat(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 // time of last status change
182 pTm = localtime(&statbuf.st_ctime);
183 SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
184 r = dateTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
185 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
187 if (__pCurDirEntry == null)
189 __pCurDirEntry = _DirEntryImpl::CreateDirEntryInstanceN();
190 SysTryReturnResult(NID_IO, __pCurDirEntry != null, E_OUT_OF_MEMORY,
191 "DirEntry allocation failed.");
194 pDirEntryName = &dirEnt.d_name[0];
196 // check for a hidden file/directory including . and ..
197 if (dirEnt.d_name[0] == '.')
202 _DirEntryImpl::GetInstance(__pCurDirEntry)->Set(dateTime, statbuf.st_size, String(dirEnt.d_name),
203 S_ISDIR(statbuf.st_mode), (statbuf.st_mode & S_IWUSR) ? false : true, hidden);
209 _DirEnumeratorImpl::Reset(void)
211 result r = E_SUCCESS;
215 delete __pCurDirEntry;
216 __pCurDirEntry = null;
219 // close and reopen the dir
222 closedir(static_cast <DIR*>(__pFileFindInfo));
225 unique_ptr<char[]> pDirPathName(_StringConverter::CopyToCharArrayN(__absoluteDirPath));
226 SysTryReturn(NID_IO, pDirPathName != null, GetLastResult(), GetLastResult(),
227 "[%s] Failed to close file.", GetErrorMessage(GetLastResult()));
229 __pFileFindInfo = opendir(pDirPathName.get());
230 if (__pFileFindInfo == null)
232 r = __ConvertNativeErrorToResult(errno);
233 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPathName.get());
240 _DirEnumeratorImpl::GetInstance(DirEnumerator& dirEnumerator)
242 return dirEnumerator.__pDirEnumeratorImpl;
245 const _DirEnumeratorImpl*
246 _DirEnumeratorImpl::GetInstance(const DirEnumerator& dirEnumerator)
248 return dirEnumerator.__pDirEnumeratorImpl;
252 _DirEnumeratorImpl::CreateDirEnumeratorInstanceN(const String& dirPath)
254 unique_ptr<DirEnumerator> pDirEnumerator(new (std::nothrow) DirEnumerator(dirPath));
255 SysTryReturn(NID_IO, pDirEnumerator != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
256 return pDirEnumerator.release();