Drizzled Public API Documentation

cached_directory.cc

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00028 #include <config.h>
00029 
00030 #include <drizzled/definitions.h>
00031 
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <unistd.h>
00035 
00036 #include <strings.h>
00037 #include <limits.h>
00038 
00039 #include <drizzled/cached_directory.h>
00040 #include <drizzled/util/find_ptr.h>
00041 
00042 using namespace std;
00043 
00044 namespace drizzled
00045 {
00046 
00047 CachedDirectory::CachedDirectory() : 
00048   error(0)
00049 {
00050 }
00051 
00052 
00053 CachedDirectory::CachedDirectory(const string &in_path) :
00054   error(0),
00055   use_full_path(false)
00056 {
00057   // TODO: Toss future exception
00058   (void) open(in_path);
00059 }
00060 
00061 
00062 CachedDirectory::CachedDirectory(const string& in_path, set<string>& allowed_exts) :
00063   error(0),
00064   use_full_path(false)
00065 {
00066   // TODO: Toss future exception
00067   (void) open(in_path, allowed_exts);
00068 }
00069 
00070 CachedDirectory::CachedDirectory(const string& in_path, enum CachedDirectory::FILTER filter, bool use_full_path_arg) :
00071   error(0),
00072   use_full_path(use_full_path_arg)
00073 {
00074   set<string> empty;
00075   // TODO: Toss future exception
00076   (void) open(in_path, empty, filter);
00077 }
00078 
00079 
00080 CachedDirectory::~CachedDirectory()
00081 {
00082   for (Entries::iterator iter= entries.begin(); iter != entries.end(); ++iter)
00083   {
00084     delete *iter;
00085   }
00086   entries.clear();
00087 }
00088 
00089 bool CachedDirectory::open(const string &in_path)
00090 {
00091   set<string> empty;
00092 
00093   return open(in_path, empty);
00094 }
00095 
00096 bool CachedDirectory::open(const string &in_path, set<string> &allowed_exts)
00097 {
00098   return open(in_path, allowed_exts, CachedDirectory::NONE);
00099 }
00100 
00101 bool CachedDirectory::open(const string &in_path, set<string> &allowed_exts, enum CachedDirectory::FILTER filter)
00102 {
00103   DIR *dirp= opendir(in_path.c_str());
00104 
00105   if (dirp == NULL)
00106   {
00107     error= errno;
00108     return false;
00109   }
00110 
00111   path= in_path;
00112 
00113   union {
00114     dirent entry;
00115 #ifdef __sun
00116     /*
00117      * The readdir_r() call on Solaris operates a bit differently from other
00118      * systems in that the dirent structure must be allocated along with enough
00119      * space to contain the filename (see man page for readdir_r on Solaris).
00120      * Instead of dynamically try to allocate this buffer, just set the max
00121      * name for a path instead.
00122      */
00123     char space[sizeof(dirent) + PATH_MAX + 1];
00124 #endif
00125   } buffer;
00126 
00127   int retcode;
00128   dirent *result;
00129 
00130   while ((retcode= readdir_r(dirp, &buffer.entry, &result)) == 0 &&
00131          result != NULL)
00132   {
00133     std::string buffered_fullpath;
00134     if (not allowed_exts.empty())
00135     {
00136       char *ptr= rindex(result->d_name, '.');
00137       if (ptr && allowed_exts.count(ptr))
00138       {
00139         entries.push_back(new Entry(result->d_name));
00140       }
00141     }
00142     else
00143     {
00144       switch (filter)
00145       {
00146       case DIRECTORY:
00147         {
00148           struct stat entrystat;
00149 
00150           if (result->d_name[0] == '.') // We don't pass back anything hidden at the moment.
00151             continue;
00152 
00153           if (use_full_path)
00154           {
00155             buffered_fullpath.append(in_path);
00156             if (buffered_fullpath[buffered_fullpath.length()] != '/')
00157               buffered_fullpath.append(1, FN_LIBCHAR);
00158           }
00159 
00160           buffered_fullpath.append(result->d_name);
00161 
00162           stat(buffered_fullpath.c_str(), &entrystat);
00163 
00164           if (S_ISDIR(entrystat.st_mode))
00165           {
00166             entries.push_back(new Entry(result->d_name));
00167           }
00168         }
00169         break;
00170       case FILE:
00171         {
00172           struct stat entrystat;
00173 
00174           buffered_fullpath.append(in_path);
00175           if (buffered_fullpath[buffered_fullpath.length()] != '/')
00176             buffered_fullpath.append(1, FN_LIBCHAR);
00177 
00178           buffered_fullpath.assign(result->d_name);
00179 
00180           stat(buffered_fullpath.c_str(), &entrystat);
00181 
00182           if (S_ISREG(entrystat.st_mode))
00183           {
00184             entries.push_back(new Entry(result->d_name));
00185           }
00186         }
00187         break;
00188       case NONE:
00189       case MAX:
00190         entries.push_back(new Entry(result->d_name));
00191         break;
00192       }
00193     }
00194   }
00195     
00196   closedir(dirp);
00197   error= retcode;
00198 
00199   return error == 0;
00200 }
00201 
00202 } /* namespace drizzled */