00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00015 #include "findfile.hpp"
00016 #include <dirent.h>
00017 #include <string.h>
00018 #include <errno.h>
00019 #include <sys/stat.h>
00020 #include <list>
00021 #include "stringbuf.hpp"
00022 #include "namematcher.hpp"
00023
00024 using namespace std;
00025
00026 namespace {
00027
00029 struct AutoDIR {
00031 DIR* d;
00032
00034 AutoDIR(DIR* d_) : d(d_) {}
00036 ~AutoDIR() { closedir(d); }
00037 };
00038
00044 class FindFileImpl : public FindFile {
00049 virtual bool find(const std::string& dir, bool recur,
00050 const std::string& mask, FindFileCallback& cb);
00051 };
00052
00053 bool FindFileImpl::find(const std::string& dir, bool recur,
00054 const std::string& mask, FindFileCallback& cb)
00055 {
00056 try {
00057 DIR *d=opendir(dir.c_str());
00058 if (!d) {
00059 throw newCException(_FLINE_, StringBuf("Can't open \"")+dir+
00060 "\" directory: "+strerror(errno));
00061 }
00062 AutoDIR autoDIR(d);
00063
00064 typedef list<string> list_type;
00065 list_type subDirs;
00066
00067 sh_ptr<NameMatcher> nm=Factory::newNameMatcher(mask);
00068
00069 struct stat statbuf;
00070 dirent *ent;
00071 while (ent=readdir(d)) {
00072 if (!strcmp(ent->d_name,".") || !strcmp(ent->d_name,"..")) continue;
00073
00074 string fname(StringBuf(dir)+"/"+ent->d_name);
00075 if (stat(fname.c_str(), &statbuf)) {
00076 throw newCException(_FLINE_, StringBuf("Can't stat \"")+fname+
00077 "\": "+strerror(errno));
00078 }
00079
00080 if (statbuf.st_mode&S_IFDIR) {
00081 subDirs.push_back(fname);
00082 continue;
00083 }
00084
00085 if (!nm->match(ent->d_name)) continue;
00086
00087 if (!cb.found(fname)) return 0;
00088 }
00089
00090 if (recur) {
00091 for (list_type::const_iterator cit=subDirs.begin(), cend=subDirs.end();
00092 cit!=cend; ++cit) {
00093 if (!find(*cit, recur, mask, cb)) return 0;
00094 }
00095 }
00096
00097 return 1;
00098 }
00099 catch (...) {
00100 throw newCException(_FLINE_, StringBuf("Can't process \"")+dir+
00101 "\" directory", toCException(_FLINE_));
00102 }
00103 }
00104
00105 }
00106
00107 sh_ptr<FindFile> Factory::newFindFile()
00108 {
00109 try { return sh_ptr<FindFile>(new FindFileImpl); }
00110 catch (...) {
00111 throw newCException(_FLINE_, "Can't create FindFileImpl object",
00112 toCException(_FLINE_));
00113 }
00114 }