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