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 #ifdef __GNU__
126  // on hurd you need UCHAR_MAX ...
127  char space[sizeof(dirent) + UCHAR_MAX + 1];
128 #endif
129  } buffer;
130 
131  int retcode;
132  dirent *result;
133 
134  while ((retcode= readdir_r(dirp, &buffer.entry, &result)) == 0 &&
135  result != NULL)
136  {
137  std::string buffered_fullpath;
138  if (not allowed_exts.empty())
139  {
140  char *ptr= rindex(result->d_name, '.');
141  if (ptr && allowed_exts.count(ptr))
142  {
143  entries.push_back(new Entry(result->d_name));
144  }
145  }
146  else
147  {
148  switch (filter)
149  {
150  case DIRECTORY:
151  {
152  struct stat entrystat;
153 
154  if (result->d_name[0] == '.') // We don't pass back anything hidden at the moment.
155  continue;
156 
157  if (use_full_path)
158  {
159  buffered_fullpath.append(in_path);
160  if (buffered_fullpath[buffered_fullpath.length()] != '/')
161  buffered_fullpath.append(1, FN_LIBCHAR);
162  }
163 
164  buffered_fullpath.append(result->d_name);
165 
166  int err= stat(buffered_fullpath.c_str(), &entrystat);
167 
168  if (err != 0)
169  {
170  errmsg_printf(error::WARN, ER(ER_CANT_GET_STAT),
171  buffered_fullpath.c_str(),
172  errno);
173  }
174 
175  if (err == 0 && S_ISDIR(entrystat.st_mode))
176  {
177  entries.push_back(new Entry(result->d_name));
178  }
179  }
180  break;
181  case FILE:
182  {
183  struct stat entrystat;
184 
185  buffered_fullpath.append(in_path);
186  if (buffered_fullpath[buffered_fullpath.length() - 1] != '/')
187  buffered_fullpath.append(1, FN_LIBCHAR);
188 
189  buffered_fullpath= result->d_name;
190 
191  stat(buffered_fullpath.c_str(), &entrystat);
192 
193  if (S_ISREG(entrystat.st_mode))
194  {
195  entries.push_back(new Entry(result->d_name));
196  }
197  }
198  break;
199  case NONE:
200  case MAX:
201  entries.push_back(new Entry(result->d_name));
202  break;
203  }
204  }
205  }
206 
207  closedir(dirp);
208  error= retcode;
209 
210  return error == 0;
211 }
212 
213 std::ostream& operator<<(std::ostream& output, const CachedDirectory &directory)
214 {
215  output << "CachedDirectory:(Path: " << directory.getPath() << ")\n";
216  BOOST_FOREACH(const CachedDirectory::Entry* iter, directory.getEntries())
217  output << "\t(" << iter->filename << ")\n";
218  return output;
219 }
220 
221 } /* namespace drizzled */
Entries entries
Entries in the directory.
const Entries & getEntries() const
std::string path
Path to the directory.
const char * getPath() const
bool open(const std::string &in_path)
Defines the interface to the CachedDirectory class.
int error
Error code stored from various syscalls.