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_DirEnumeratorImpl.cpp
19 * @brief This is the implementation file for _DirEnumeratorImpl class.
28 #include <unique_ptr.h>
30 #include <FBaseDateTime.h>
31 #include <FIoDirEntry.h>
32 #include <FIoDirEnumerator.h>
33 #include <FBaseSysLog.h>
35 #include <FBase_NativeError.h>
36 #include <FBase_StringConverter.h>
37 #include <FIo_DirEnumeratorImpl.h>
38 #include <FIo_DirEntryImpl.h>
41 using namespace Tizen::Base;
43 namespace Tizen { namespace Io
46 static const int _BASE_YEAR = 1900;
48 _DirEnumeratorImpl::_DirEnumeratorImpl(const String& dirPath)
49 : __validAccess(false)
50 , __pFileFindInfo(null)
51 , __pCurDirEntry(null)
54 __absoluteDirPath = dirPath;
57 _DirEnumeratorImpl::_DirEnumeratorImpl(const _DirEnumeratorImpl& dirEnumeratorImpl)
58 : __validAccess(false)
59 , __pFileFindInfo(null)
60 , __pCurDirEntry(null)
62 SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This copy constructor is not implemented.");
63 SetLastResult(E_UNSUPPORTED_OPERATION);
67 _DirEnumeratorImpl::operator =(const _DirEnumeratorImpl& dirEnumeratorImpl)
69 if (this != &dirEnumeratorImpl)
71 SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This assign operator is not implemented.");
72 SetLastResult(E_UNSUPPORTED_OPERATION);
77 _DirEnumeratorImpl::~_DirEnumeratorImpl(void)
81 closedir(static_cast <DIR*>(__pFileFindInfo));
82 __pFileFindInfo = null;
85 delete __pCurDirEntry;
89 _DirEnumeratorImpl::GetCurrentDirEntry(void) const
93 unique_ptr<DirEntry> pDirEntry(_DirEntryImpl::CreateDirEntryInstanceN());
94 DirEntry dirEntryObject = *pDirEntry;
96 SysTryReturn(NID_IO, __pCurDirEntry != null, dirEntryObject, E_INVALID_STATE,
97 "[E_INVALID_STATE] Instance has not been created yet.");
99 _DirEntryImpl::GetInstance(&dirEntryObject)->Set(__pCurDirEntry->GetDateTime(),
100 __pCurDirEntry->GetFileSize(), __pCurDirEntry->GetName(), __pCurDirEntry->IsDirectory(),
101 __pCurDirEntry->IsReadOnly(), __pCurDirEntry->IsHidden());
104 return dirEntryObject;
108 _DirEnumeratorImpl::GetCurrent(void) const
110 SetLastResult(E_SUCCESS);
111 return __pCurDirEntry;
115 _DirEnumeratorImpl::MoveNext(void)
117 result r = E_SUCCESS;
118 struct dirent dirEnt;
119 struct dirent* pDirEntResult = null;
120 struct stat64 statbuf;
121 struct tm* pTm = null;
126 char* pDirEntryName = null;
128 SysTryReturnResult(NID_IO, __validAccess == true, E_ILLEGAL_ACCESS,
129 "Given path cannot be accessed!");
130 SysTryReturnResult(NID_IO, __absoluteDirPath.GetLength() > 0 && __absoluteDirPath.GetLength() <= PATH_MAX,
131 E_INVALID_ARG, "Invalid argument was passed. Given pattern length is not correct!");
133 unique_ptr<char[]> pAbsDirPath(_StringConverter::CopyToCharArrayN(String(__absoluteDirPath)));
134 SysTryReturn(NID_IO, (pAbsDirPath != null), GetLastResult(), GetLastResult(),
135 "[%s] Invalid argument was passed. Given pattern length is not correct!", GetErrorMessage(GetLastResult()));
137 if (__pFileFindInfo == null)
139 __pFileFindInfo = opendir(pAbsDirPath.get());
140 if (__pFileFindInfo == null)
142 r = _NativeError::ConvertNativeErrorToResult(errno, true);
143 SysLog(NID_IO, "[%s] Failed to open directory (%s), [%s].", GetErrorMessage(r),
144 GetErrorMessage((result) E_FILE_NOT_FOUND), pAbsDirPath.get());
150 // move to next entry in the directory
152 ret = readdir_r((DIR*) __pFileFindInfo, &dirEnt, &pDirEntResult);
153 SysTryReturn(NID_IO, (ret == 0), __ConvertNativeErrorToResult(errno),
154 __ConvertNativeErrorToResult(errno), "[%s] Failed to read next dir entry.", __ConvertNativeErrorToMessage(errno));
156 if (pDirEntResult == null)
158 return E_END_OF_FILE; // Complete reading the directory
161 //if (dirEnt.d_name[0] == '.')
166 // prepare entry path
167 dirEntryPath.Append(__absoluteDirPath);
168 dirEntryPath.Append(L"/");
169 dirEntryPath.Append(dirEnt.d_name);
170 unique_ptr<char[]> pAbsDirEntryPath(_StringConverter::CopyToCharArrayN(dirEntryPath));
171 SysTryReturn(NID_IO, (pAbsDirEntryPath != null), GetLastResult(), GetLastResult(),
172 "[%s] Invalid argument was passed. Given pattern length is not correct!", GetErrorMessage(GetLastResult()));
175 ret = stat64(pAbsDirEntryPath.get(), &statbuf);
176 SysSecureTryReturn(NID_IO, (ret == 0), r = __ConvertNativeErrorToResult(errno), __ConvertNativeErrorToResult(errno),
177 "[%s] Failed to get attributes for dir entry (%s) whose absolute dirpath is (%s)with errno [%d].",
178 __ConvertNativeErrorToMessage(errno), dirEnt.d_name, pAbsDirPath.get(), errno);
180 pTm = localtime(&statbuf.st_mtime);
181 SysTryReturnResult(NID_IO, pTm != null, E_SYSTEM, "Failed to call localtime() (%s).", strerror(errno));
182 r = dateTime.SetValue(_BASE_YEAR + pTm->tm_year, 1 + pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
183 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
185 if (__pCurDirEntry == null)
187 __pCurDirEntry = _DirEntryImpl::CreateDirEntryInstanceN();
188 SysTryReturnResult(NID_IO, __pCurDirEntry != null, E_OUT_OF_MEMORY,
189 "DirEntry allocation failed.");
192 pDirEntryName = &dirEnt.d_name[0];
194 // check for a hidden file/directory including . and ..
195 if (dirEnt.d_name[0] == '.')
200 _DirEntryImpl::GetInstance(__pCurDirEntry)->Set(dateTime, statbuf.st_size, String(dirEnt.d_name),
201 S_ISDIR(statbuf.st_mode), (statbuf.st_mode & S_IWUSR) ? false : true, hidden);
207 _DirEnumeratorImpl::Reset(void)
209 result r = E_SUCCESS;
213 delete __pCurDirEntry;
214 __pCurDirEntry = null;
217 // close and reopen the dir
220 closedir(static_cast <DIR*>(__pFileFindInfo));
223 unique_ptr<char[]> pDirPathName(_StringConverter::CopyToCharArrayN(__absoluteDirPath));
224 SysTryReturn(NID_IO, pDirPathName != null, GetLastResult(), GetLastResult(),
225 "[%s] Failed to close file.", GetErrorMessage(GetLastResult()));
227 __pFileFindInfo = opendir(pDirPathName.get());
228 if (__pFileFindInfo == null)
230 r = __ConvertNativeErrorToResult(errno);
231 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPathName.get());
238 _DirEnumeratorImpl::GetInstance(DirEnumerator& dirEnumerator)
240 return dirEnumerator.__pDirEnumeratorImpl;
243 const _DirEnumeratorImpl*
244 _DirEnumeratorImpl::GetInstance(const DirEnumerator& dirEnumerator)
246 return dirEnumerator.__pDirEnumeratorImpl;
250 _DirEnumeratorImpl::CreateDirEnumeratorInstanceN(const String& dirPath)
252 unique_ptr<DirEnumerator> pDirEnumerator(new (std::nothrow) DirEnumerator(dirPath));
253 SysTryReturn(NID_IO, pDirEnumerator != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
254 return pDirEnumerator.release();