31 #include "DirectoryUtil.h" 36 #include <sys/types.h> 45 #include "BESForbiddenError.h" 46 #include "BESInternalError.h" 47 #include "TheBESKeys.h" 48 #include "BESNotFoundError.h" 62 DirWrapper(
const string& fullDirPath) :
63 _pDir(0), _fullPath(fullDirPath)
66 _pDir = opendir(fullDirPath.c_str());
90 std::string _fullPath;
94 FileInfo::FileInfo(
const std::string& path,
const std::string& basename,
bool isDir, time_t modTime) :
95 _path(path), _basename(basename), _fullPath(
"")
96 , _isDir(isDir), _modTime(modTime)
102 FileInfo::~FileInfo()
113 FileInfo::basename()
const 118 bool FileInfo::isDir()
const 123 time_t FileInfo::modTime()
const 131 struct tm* pTM = gmtime(&_modTime);
134 strftime(buf, 128,
"%F %T", pTM);
141 if (_fullPath.empty()) {
142 _fullPath = _path +
"/" + _basename;
147 std::string FileInfo::toString()
const 149 return "{FileInfo fullPath=" +
getFullPath() +
" isDir=" + ((isDir()) ? (
"true") : (
"false")) +
" modTime=\"" 156 const string DirectoryUtil::_sDebugChannel =
"agg_util";
158 DirectoryUtil::DirectoryUtil() :
159 _rootDir(
"/"), _suffix(
"")
160 , _pRegExp(0), _filteringModTimes(false), _newestModTime(0L)
166 DirectoryUtil::~DirectoryUtil()
187 throw BESForbiddenError(
"can't use rootDir=" + origRootDir +
" since it has a relative path (../)", __FILE__,
192 _rootDir = origRootDir;
213 if (!regexp.empty()) {
214 _pRegExp =
new libdap::Regex(regexp.c_str());
226 _newestModTime = newestModTime;
227 _filteringModTimes =
true;
231 std::vector<FileInfo>* pDirectories)
233 string pathToUse(path);
236 BESDEBUG(_sDebugChannel,
"Attempting to get dir listing for path=\"" << pathToUse <<
"\"" << endl);
239 DirWrapper pDir(pathToUse);
241 throwErrorForOpendirFail(pathToUse);
246 struct dirent* pDirEnt = 0;
247 while ((pDirEnt = readdir(pDir.get())) != 0) {
248 string entryName = pDirEnt->d_name;
250 if (!entryName.empty() && entryName[0] ==
'.') {
255 string pathToEntry = pathToUse +
"/" + entryName;
257 int statResult = stat(pathToEntry.c_str(), &statBuf);
258 if (statResult != 0) {
266 if (pDirectories && S_ISDIR(statBuf.st_mode)) {
267 pDirectories->push_back(
FileInfo(path, entryName,
true, statBuf.st_mtime));
269 else if (pRegularFiles && S_ISREG(statBuf.st_mode)) {
270 FileInfo theFile(path, entryName,
false, statBuf.st_mtime);
272 if (matchesAllFilters(theFile.
getFullPath(), statBuf.st_mtime)) {
273 pRegularFiles->push_back(theFile);
280 std::vector<FileInfo>* pDirectories)
283 string canonicalPath = path;
290 vector<FileInfo> dirs;
299 pDirectories->insert(pDirectories->end(), dirs.begin(), dirs.end());
303 for (vector<FileInfo>::const_iterator it = dirs.begin(); it != dirs.end(); ++it) {
304 string subPath = canonicalPath +
"/" + it->basename();
305 BESDEBUG(_sDebugChannel,
"DirectoryUtil: recursing down to directory subtree=\"" << subPath <<
"\"..." << endl);
318 void DirectoryUtil::throwErrorForOpendirFail(
const string& fullPath)
322 string msg =
"Permission denied for some directory in path=\"" + fullPath +
"\"";
328 string msg =
"A symlink loop was detected in path=\"" + fullPath +
"\"";
334 string msg =
"A name in the path was too long. path=\"" + fullPath +
"\"";
340 string msg =
"Some part of the path was not found. path=\"" + fullPath +
"\"";
346 string msg =
"Some part of the path was not a directory. path=\"" + fullPath +
"\"";
352 string msg =
"Internal Error: Too many files are currently open!";
358 string msg =
"An unknown errno was found after opendir() was called on path=\"" + fullPath +
"\"";
364 bool DirectoryUtil::matchesAllFilters(
const std::string& path, time_t modTime)
const 368 if (!_suffix.empty() && !matchesSuffix(path, _suffix)) {
373 if (matches && _pRegExp) {
375 int numCharsMatching = _pRegExp->match(path.c_str(), path.size(), 0);
376 matches = (numCharsMatching > 0);
379 if (matches && _filteringModTimes) {
380 matches = (modTime < _newestModTime);
388 return (path.find(
"..") != string::npos);
394 string::size_type pos = path.find_last_not_of(
"/");
395 if (pos != string::npos) {
396 path = path.substr(0, pos + 1);
404 string::size_type pos = path.find_first_not_of(
"/");
405 path = path.substr(pos, string::npos);
411 std::ostringstream oss;
413 BESDEBUG(_sDebugChannel, oss.str() << endl);
418 for (vector<FileInfo>::const_iterator it = listing.begin(); it != listing.end(); ++it) {
419 os << it->toString() << endl;
437 bool DirectoryUtil::matchesSuffix(
const std::string& filename,
const std::string& suffix)
440 bool matches = (filename.find(suffix, filename.size() - suffix.size()) != string::npos);
std::string getModTimeAsString() const
error thrown if the resource requested cannot be found
FileInfo(const std::string &path, const std::string &basename, bool isDir, time_t modTime)
void getListingOfRegularFilesRecursive(const std::string &path, std::vector< FileInfo > &rRegularFiles)
void setFilterRegExp(const std::string ®exp)
const std::string & getRootDir() const
exception thrown if inernal error encountered
void getListingForPath(const std::string &path, std::vector< FileInfo > *pRegularFiles, std::vector< FileInfo > *pDirectories)
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
const std::string & getFullPath() const
static TheBESKeys * TheKeys()
void setFilterSuffix(const std::string &suffix)
static std::string getBESRootDir()
static void removeTrailingSlashes(std::string &path)
error thrown if the BES is not allowed to access the resource requested
void setFilterModTimeOlderThan(time_t newestModTime)
void setRootDir(const std::string &rootDir, bool allowRelativePaths=false, bool allowSymLinks=false)
static void check_path(const string &path, const string &root, bool follow_sym_links)
Check if the specified path is valid.
static void removePrecedingSlashes(std::string &path)
void getListingForPathRecursive(const std::string &path, std::vector< FileInfo > *pRegularFiles, std::vector< FileInfo > *pDirectories)
static void printFileInfoList(std::ostream &os, const std::vector< FileInfo > &listing)
static bool hasRelativePath(const std::string &path)
const std::string & path() const