Drizzled Public API Documentation

cached_directory.cc
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
28 #include <config.h>
29 #include <dirent.h>
30 #include <drizzled/definitions.h>
31 
32 #include <boost/foreach.hpp>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 
37 #include <strings.h>
38 #include <limits.h>
39 
41 #include <drizzled/util/find_ptr.h>
42 #include <drizzled/error_t.h>
43 #include <drizzled/error.h>
44 #include <drizzled/errmsg_print.h>
45 
46 using namespace std;
47 using namespace drizzled;
48 
49 namespace drizzled {
50 
51 CachedDirectory::CachedDirectory() :
52  error(0)
53 {
54 }
55 
56 
57 CachedDirectory::CachedDirectory(const string &in_path) :
58  error(0),
59  use_full_path(false)
60 {
61  // TODO: Toss future exception
62  (void) open(in_path);
63 }
64 
65 
66 CachedDirectory::CachedDirectory(const string& in_path, set<string>& allowed_exts) :
67  error(0),
68  use_full_path(false)
69 {
70  // TODO: Toss future exception
71  (void) open(in_path, allowed_exts);
72 }
73 
74 CachedDirectory::CachedDirectory(const string& in_path, enum CachedDirectory::FILTER filter, bool use_full_path_arg) :
75  error(0),
76  use_full_path(use_full_path_arg)
77 {
78  set<string> empty;
79  // TODO: Toss future exception
80  (void) open(in_path, empty, filter);
81 }
82 
83 
85 {
86  BOOST_FOREACH(Entries::reference iter, entries)
87  delete iter;
88 }
89 
90 bool CachedDirectory::open(const string &in_path)
91 {
92  set<string> empty;
93  return open(in_path, empty);
94 }
95 
96 bool CachedDirectory::open(const string &in_path, set<string> &allowed_exts)
97 {
98  return open(in_path, allowed_exts, CachedDirectory::NONE);
99 }
100 
101 bool CachedDirectory::open(const string &in_path, set<string> &allowed_exts, enum CachedDirectory::FILTER filter)
102 {
103  DIR *dirp= opendir(in_path.c_str());
104 
105  if (dirp == NULL)
106  {
107  error= errno;
108  return false;
109  }
110 
111  path= in_path;
112 
113  union {
114  dirent entry;
115 #ifdef __sun
116  /*
117  * The readdir_r() call on Solaris operates a bit differently from other
118  * systems in that the dirent structure must be allocated along with enough
119  * space to contain the filename (see man page for readdir_r on Solaris).
120  * Instead of dynamically try to allocate this buffer, just set the max
121  * name for a path instead.
122  */
123  char space[sizeof(dirent) + PATH_MAX + 1];
124 #endif
125  } buffer;
126 
127  int retcode;
128  dirent *result;
129 
130  while ((retcode= readdir_r(dirp, &buffer.entry, &result)) == 0 &&
131  result != NULL)
132  {
133  std::string buffered_fullpath;
134  if (not allowed_exts.empty())
135  {
136  char *ptr= rindex(result->d_name, '.');
137  if (ptr && allowed_exts.count(ptr))
138  {
139  entries.push_back(new Entry(result->d_name));
140  }
141  }
142  else
143  {
144  switch (filter)
145  {
146  case DIRECTORY:
147  {
148  struct stat entrystat;
149 
150  if (result->d_name[0] == '.') // We don't pass back anything hidden at the moment.
151  continue;
152 
153  if (use_full_path)
154  {
155  buffered_fullpath.append(in_path);
156  if (buffered_fullpath[buffered_fullpath.length()] != '/')
157  buffered_fullpath.append(1, FN_LIBCHAR);
158  }
159 
160  buffered_fullpath.append(result->d_name);
161 
162  int err= stat(buffered_fullpath.c_str(), &entrystat);
163 
164  if (err != 0)
165  {
166  errmsg_printf(error::WARN, ER(ER_CANT_GET_STAT),
167  buffered_fullpath.c_str(),
168  errno);
169  }
170 
171  if (err == 0 && S_ISDIR(entrystat.st_mode))
172  {
173  entries.push_back(new Entry(result->d_name));
174  }
175  }
176  break;
177  case FILE:
178  {
179  struct stat entrystat;
180 
181  buffered_fullpath.append(in_path);
182  if (buffered_fullpath[buffered_fullpath.length() - 1] != '/')
183  buffered_fullpath.append(1, FN_LIBCHAR);
184 
185  buffered_fullpath= result->d_name;
186 
187  stat(buffered_fullpath.c_str(), &entrystat);
188 
189  if (S_ISREG(entrystat.st_mode))
190  {
191  entries.push_back(new Entry(result->d_name));
192  }
193  }
194  break;
195  case NONE:
196  case MAX:
197  entries.push_back(new Entry(result->d_name));
198  break;
199  }
200  }
201  }
202 
203  closedir(dirp);
204  error= retcode;
205 
206  return error == 0;
207 }
208 
209 std::ostream& operator<<(std::ostream& output, const CachedDirectory &directory)
210 {
211  output << "CachedDirectory:(Path: " << directory.getPath() << ")\n";
212  BOOST_FOREACH(const CachedDirectory::Entry* iter, directory.getEntries())
213  output << "\t(" << iter->filename << ")\n";
214  return output;
215 }
216 
217 } /* namespace drizzled */