31#include "DirectoryUtil.h"
44#include "BESForbiddenError.h"
45#include "BESInternalError.h"
46#include "TheBESKeys.h"
47#include "BESNotFoundError.h"
62 DirWrapper(
const string& fullDirPath) :
63 _pDir(0), _fullPath(fullDirPath)
66 _pDir = opendir(fullDirPath.c_str());
90 std::string _fullPath;
95 _path(
path), _basename(basename), _fullPath(
"")
96 , _isDir(isDir), _modTime(modTime)
113FileInfo::basename()
const
118bool FileInfo::isDir()
const
123time_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;
147std::string FileInfo::toString()
const
149 return "{FileInfo fullPath=" +
getFullPath() +
" isDir=" + ((isDir()) ? (
"true") : (
"false")) +
" modTime=\""
156const string DirectoryUtil::_sDebugChannel =
"agg_util";
158DirectoryUtil::DirectoryUtil() :
159 _rootDir(
"/"), _suffix(
"")
160 , _pRegExp(0), _filteringModTimes(false), _newestModTime(0L)
166DirectoryUtil::~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 BESRegex(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());
304 string subPath = canonicalPath +
"/" + it->basename();
305 BESDEBUG(_sDebugChannel,
"DirectoryUtil: recursing down to directory subtree=\"" << subPath <<
"\"..." << endl);
318void 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 +
"\"";
335 throw BESNotFoundError(msg, __FILE__, __LINE__);
340 string msg =
"Some part of the path was not found. path=\"" + fullPath +
"\"";
341 throw BESNotFoundError(msg, __FILE__, __LINE__);
346 string msg =
"Some part of the path was not a directory. path=\"" + fullPath +
"\"";
347 throw BESNotFoundError(msg, __FILE__, __LINE__);
352 string msg =
"Internal Error: Too many files are currently open!";
353 throw BESInternalError(msg, __FILE__, __LINE__);
358 string msg =
"An unknown errno was found after opendir() was called on path=\"" + fullPath +
"\"";
359 throw BESInternalError(msg, __FILE__, __LINE__);
364bool 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);
419 os << it->toString() << endl;
437bool DirectoryUtil::matchesSuffix(
const std::string& filename,
const std::string& suffix)
440 bool matches = (filename.find(suffix, filename.size() - suffix.size()) != string::npos);
error thrown if the BES is not allowed to access the resource requested
error thrown if the resource requested cannot be found
Regular expression matching.
static void check_path(const std::string &path, const std::string &root, bool follow_sym_links)
Is the combination of root + path a pathname the BES can/should access?
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.
static std::string getBESRootDir()
void setFilterRegExp(const std::string ®exp)
static void removePrecedingSlashes(std::string &path)
static bool hasRelativePath(const std::string &path)
static void printFileInfoList(std::ostream &os, const std::vector< FileInfo > &listing)
void setRootDir(const std::string &rootDir, bool allowRelativePaths=false, bool allowSymLinks=false)
void getListingOfRegularFilesRecursive(const std::string &path, std::vector< FileInfo > &rRegularFiles)
void setFilterSuffix(const std::string &suffix)
static void removeTrailingSlashes(std::string &path)
void getListingForPath(const std::string &path, std::vector< FileInfo > *pRegularFiles, std::vector< FileInfo > *pDirectories)
void getListingForPathRecursive(const std::string &path, std::vector< FileInfo > *pRegularFiles, std::vector< FileInfo > *pDirectories)
void setFilterModTimeOlderThan(time_t newestModTime)
const std::string & getRootDir() const
std::string getModTimeAsString() const
FileInfo(const std::string &path, const std::string &basename, bool isDir, time_t modTime)
const std::string & path() const
const std::string & getFullPath() const
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...