1 /*
2 ** Copyright 2012-2013 Centreon
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 ** For more information : contact@centreon.com
17 */
18 
19 #include "com/centreon/io/directory_entry.hh"
20 #include <dirent.h>
21 #include <unistd.h>
22 #include <cerrno>
23 #include <cstdlib>
24 #include <cstring>
25 #include "com/centreon/exceptions/basic.hh"
26 
27 using namespace com::centreon::io;
28 
29 /**
30  *  Constructor.
31  *
32  *  @param[in] path  The directory path.
33  */
directory_entry(char const * path)34 directory_entry::directory_entry(char const* path) : _entry(path) {}
35 
36 /**
37  *  Constructor.
38  *
39  *  @param[in] path  The directory path.
40  */
directory_entry(std::string const & path)41 directory_entry::directory_entry(std::string const& path) : _entry(path) {}
42 
43 /**
44  *  Copy constructor.
45  *
46  *  @param[in] right  The object to copy.
47  */
directory_entry(directory_entry const & right)48 directory_entry::directory_entry(directory_entry const& right) {
49   _internal_copy(right);
50 }
51 
52 /**
53  *  Copy operator.
54  *
55  *  @param[in] right  The object to copy.
56  *
57  *  @return This object.
58  */
operator =(directory_entry const & right)59 directory_entry& directory_entry::operator=(directory_entry const& right) {
60   _internal_copy(right);
61   return *this;
62 }
63 
64 /**
65  *  Equal operator.
66  *
67  *  @param[in] right  The object to compare.
68  *
69  *  @return True if is the same object, owtherwise false.
70  */
operator ==(directory_entry const & right) const71 bool directory_entry::operator==(directory_entry const& right) const noexcept {
72   return _entry == right._entry;
73 }
74 
75 /**
76  *  Not equal operator.
77  *
78  *  @param[in] right  The object to compare.
79  *
80  *  @return True if is not the same object, owtherwise false.
81  */
operator !=(directory_entry const & right) const82 bool directory_entry::operator!=(directory_entry const& right) const noexcept {
83   return !operator==(right);
84 }
85 
86 /**
87  *  Destructor.
88  */
~directory_entry()89 directory_entry::~directory_entry() noexcept {}
90 
91 /**
92  *  Get the current directory path.
93  *
94  *  @return The current directory path.
95  */
current_path()96 std::string directory_entry::current_path() {
97   char* buffer(getcwd(NULL, 0));
98   if (!buffer)
99     throw(basic_error() << "current path failed");
100   std::string path(buffer);
101   free(buffer);
102   return path;
103 }
104 
105 /**
106  *  Get the directory information.
107  *
108  *  @return The directory entry.
109  */
entry() const110 file_entry const& directory_entry::entry() const noexcept {
111   return _entry;
112 }
113 
114 /**
115  *  Get the list of all entry into a directory.
116  *
117  *  @param[in] filter  An optional filter.
118  *
119  *  @return The file entry list.
120  */
entry_list(std::string const & filter)121 std::list<file_entry> const& directory_entry::entry_list(
122     std::string const& filter) {
123   _entry_lst.clear();
124   char const* filter_ptr(filter.empty() ? NULL : filter.c_str());
125 
126   DIR* dir(opendir(_entry.path().c_str()));
127   if (!dir) {
128     char const* msg(strerror(errno));
129     throw(basic_error() << "open directory failed: " << msg);
130   }
131 
132   dirent entry;
133   dirent* result;
134   while (true) {
135     if (readdir_r(dir, &entry, &result)) {
136       closedir(dir);
137       throw(basic_error() << "parse directory failed");
138     }
139     if (!result)
140       break;
141     if (!filter_ptr || _nmatch(entry.d_name, filter_ptr))
142       _entry_lst.push_back(file_entry(_entry.path() + "/" + entry.d_name));
143   }
144   closedir(dir);
145 
146   return _entry_lst;
147 }
148 
149 /**
150  *  Internal copy.
151  *
152  *  @param[in] right  The object to copy.
153  */
_internal_copy(directory_entry const & right)154 void directory_entry::_internal_copy(directory_entry const& right) {
155   if (this != &right) {
156     _entry = right._entry;
157     _entry_lst = right._entry_lst;
158   }
159 }
160 
161 /**
162  *  Check if a string match a pattern.
163  *
164  *  @param[in] str      The string to check.
165  *  @param[in] pattern  The partter to match.
166  *
167  *  @return 1 on success, otherwiswe 0.
168  */
_nmatch(char const * str,char const * pattern)169 int directory_entry::_nmatch(char const* str, char const* pattern) {
170   if (!*str && !*pattern)
171     return 1;
172   if (*str == *pattern)
173     return _nmatch(str + 1, pattern + 1);
174   return (*pattern == '*' ? (*str ? _nmatch(str + 1, pattern) : 0) +
175                                 _nmatch(str, pattern + 1)
176                           : 0);
177 }
178