Merge "Update doxygen" into tizen_2.1
[platform/framework/native/appfw.git] / src / io / FIo_DirEnumeratorImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 /**
19  * @file        FIo_DirEnumeratorImpl.cpp
20  * @brief       This is the implementation file for _DirEnumeratorImpl class.
21  */
22
23 #include <string.h>
24 #include <dirent.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <limits.h>
29 #include <unique_ptr.h>
30
31 #include <FBaseDateTime.h>
32 #include <FIoDirEntry.h>
33 #include <FIoDirEnumerator.h>
34 #include <FBaseSysLog.h>
35
36 #include <FBase_NativeError.h>
37 #include <FBase_StringConverter.h>
38 #include <FIo_DirEnumeratorImpl.h>
39 #include <FIo_DirEntryImpl.h>
40
41 using namespace std;
42 using namespace Tizen::Base;
43
44 namespace Tizen { namespace Io
45 {
46
47 static const int _BASE_YEAR = 1900;
48
49 _DirEnumeratorImpl::_DirEnumeratorImpl(const String& dirPath)
50         : __validAccess(false)
51         , __pFileFindInfo(null)
52         , __pCurDirEntry(null)
53 {
54         __validAccess = true;
55         __absoluteDirPath = dirPath;
56 }
57
58 _DirEnumeratorImpl::_DirEnumeratorImpl(const _DirEnumeratorImpl& dirEnumeratorImpl)
59         : __validAccess(false)
60         , __pFileFindInfo(null)
61         , __pCurDirEntry(null)
62 {
63         SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This copy constructor is not implemented.");
64         SetLastResult(E_UNSUPPORTED_OPERATION);
65 }
66
67 _DirEnumeratorImpl&
68 _DirEnumeratorImpl::operator =(const _DirEnumeratorImpl& dirEnumeratorImpl)
69 {
70         if (this != &dirEnumeratorImpl)
71         {
72                 SysLogException(NID_IO, E_UNSUPPORTED_OPERATION, "[E_UNSUPPORTED_OPERATION] This assign operator is not implemented.");
73                 SetLastResult(E_UNSUPPORTED_OPERATION);
74         }
75         return *this;
76 }
77
78 _DirEnumeratorImpl::~_DirEnumeratorImpl(void)
79 {
80         if (__pFileFindInfo)
81         {
82                 closedir(static_cast <DIR*>(__pFileFindInfo));
83                 __pFileFindInfo = null;
84         }
85
86         delete __pCurDirEntry;
87 }
88
89 DirEntry
90 _DirEnumeratorImpl::GetCurrentDirEntry(void) const
91 {
92         result r = E_SUCCESS;
93
94         unique_ptr<DirEntry> pDirEntry(_DirEntryImpl::CreateDirEntryInstanceN());
95         DirEntry dirEntryObject = *pDirEntry;
96
97         SysTryReturn(NID_IO, __pCurDirEntry != null, dirEntryObject, E_INVALID_STATE,
98                         "[E_INVALID_STATE] Instance has not been created yet.");
99
100         _DirEntryImpl::GetInstance(&dirEntryObject)->Set(__pCurDirEntry->GetDateTime(),
101                         __pCurDirEntry->GetFileSize(), __pCurDirEntry->GetName(), __pCurDirEntry->IsDirectory(),
102                         __pCurDirEntry->IsReadOnly(), __pCurDirEntry->IsHidden());
103
104         SetLastResult(r);
105         return dirEntryObject;
106 }
107
108 Object*
109 _DirEnumeratorImpl::GetCurrent(void) const
110 {
111         SetLastResult(E_SUCCESS);
112         return __pCurDirEntry;
113 }
114
115 result
116 _DirEnumeratorImpl::MoveNext(void)
117 {
118         result r = E_SUCCESS;
119         struct dirent dirEnt;
120         struct dirent* pDirEntResult = null;
121         struct stat64 statbuf;
122         struct tm* pTm = null;
123         DateTime dateTime;
124         int ret = 0;
125         String dirEntryPath;
126         bool hidden = false;
127         char* pDirEntryName = null;
128
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!");
133
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()));
137
138         if (__pFileFindInfo == null)
139         {
140                 __pFileFindInfo = opendir(pAbsDirPath.get());
141                 if (__pFileFindInfo == null)
142                 {
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());
146                         return r;
147                 }
148         }
149
150 //SKIP_DIR:
151         // move to next entry in the directory
152         errno = 0;
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));
156
157         if (pDirEntResult == null)
158         {
159                 return E_END_OF_FILE; // Complete reading the directory
160         }
161
162         //if (dirEnt.d_name[0] == '.')
163         //{
164         //      goto SKIP_DIR;
165         //}
166
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()));
174
175         // get its details
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);
180
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));
185
186         if (__pCurDirEntry == null)
187         {
188                 __pCurDirEntry = _DirEntryImpl::CreateDirEntryInstanceN();
189                 SysTryReturnResult(NID_IO, __pCurDirEntry != null, E_OUT_OF_MEMORY,
190                                    "DirEntry allocation failed.");
191         }
192
193         pDirEntryName = &dirEnt.d_name[0];
194
195         // check for a hidden file/directory including . and ..
196         if (dirEnt.d_name[0] == '.')
197         {
198                 hidden = true;
199         }
200
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);
203
204         return E_SUCCESS;
205 }
206
207 result
208 _DirEnumeratorImpl::Reset(void)
209 {
210         result r = E_SUCCESS;
211
212         if (__pCurDirEntry)
213         {
214                 delete __pCurDirEntry;
215                 __pCurDirEntry = null;
216         }
217
218         // close and reopen the dir
219         if (__pFileFindInfo)
220         {
221                 closedir(static_cast <DIR*>(__pFileFindInfo));
222         }
223
224         unique_ptr<char[]> pDirPathName(_StringConverter::CopyToCharArrayN(__absoluteDirPath));
225         SysTryReturn(NID_IO, pDirPathName != null, GetLastResult(), GetLastResult(),
226                         "[%s] Failed to close file.", GetErrorMessage(GetLastResult()));
227
228         __pFileFindInfo = opendir(pDirPathName.get());
229         if (__pFileFindInfo == null)
230         {
231                 r = __ConvertNativeErrorToResult(errno);
232                 SysLog(NID_IO, "[%s] Failed to open directory (%s).", GetErrorMessage(r), pDirPathName.get());
233         }
234
235         return r;
236 }
237
238 _DirEnumeratorImpl*
239 _DirEnumeratorImpl::GetInstance(DirEnumerator& dirEnumerator)
240 {
241         return dirEnumerator.__pDirEnumeratorImpl;
242 }
243
244 const _DirEnumeratorImpl*
245 _DirEnumeratorImpl::GetInstance(const DirEnumerator& dirEnumerator)
246 {
247         return dirEnumerator.__pDirEnumeratorImpl;
248 }
249
250 DirEnumerator*
251 _DirEnumeratorImpl::CreateDirEnumeratorInstanceN(const String& dirPath)
252 {
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();
256 }
257
258 }} // Tizen::Io
259