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;
94FileInfo::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)
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());
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);
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 +
"\"";
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 +
"\"";
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);
418 for (vector<FileInfo>::const_iterator it = listing.begin(); it != listing.end(); ++it) {
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
exception thrown if internal error encountered
error thrown if the resource requested cannot be found
Regular expression matching.
int match(const char *s, int len, int pos=0) const
Does the pattern match.
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()
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...