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"
63 DirWrapper(
const string& fullDirPath) :
64 _pDir(0), _fullPath(fullDirPath)
67 _pDir = opendir(fullDirPath.c_str());
91 std::string _fullPath;
95 FileInfo::FileInfo(
const std::string& path,
const std::string& basename,
bool isDir, time_t modTime) :
96 _path(path), _basename(basename), _fullPath(
"")
97 , _isDir(isDir), _modTime(modTime)
103 FileInfo::~FileInfo()
114 FileInfo::basename()
const
119 bool FileInfo::isDir()
const
124 time_t FileInfo::modTime()
const
132 struct tm* pTM = gmtime(&_modTime);
135 strftime(buf, 128,
"%F %T", pTM);
142 if (_fullPath.empty()) {
143 _fullPath = _path +
"/" + _basename;
148 std::string FileInfo::toString()
const
150 return "{FileInfo fullPath=" +
getFullPath() +
" isDir=" + ((isDir()) ? (
"true") : (
"false")) +
" modTime=\""
157 const string DirectoryUtil::_sDebugChannel =
"agg_util";
159 DirectoryUtil::DirectoryUtil() :
160 _rootDir(
"/"), _suffix(
"")
161 , _pRegExp(0), _filteringModTimes(false), _newestModTime(0L)
167 DirectoryUtil::~DirectoryUtil()
188 throw BESForbiddenError(
"can't use rootDir=" + origRootDir +
" since it has a relative path (../)", __FILE__,
193 _rootDir = origRootDir;
214 if (!regexp.empty()) {
215 _pRegExp =
new libdap::Regex(regexp.c_str());
227 _newestModTime = newestModTime;
228 _filteringModTimes =
true;
232 std::vector<FileInfo>* pDirectories)
234 string pathToUse(path);
237 BESDEBUG(_sDebugChannel,
"Attempting to get dir listing for path=\"" << pathToUse <<
"\"" << endl);
240 DirWrapper pDir(pathToUse);
242 throwErrorForOpendirFail(pathToUse);
247 struct dirent* pDirEnt = 0;
248 while ((pDirEnt = readdir(pDir.get())) != 0) {
249 string entryName = pDirEnt->d_name;
251 if (!entryName.empty() && entryName[0] ==
'.') {
256 string pathToEntry = pathToUse +
"/" + entryName;
258 int statResult = stat(pathToEntry.c_str(), &statBuf);
259 if (statResult != 0) {
267 if (pDirectories && S_ISDIR(statBuf.st_mode)) {
268 pDirectories->push_back(
FileInfo(path, entryName,
true, statBuf.st_mtime));
270 else if (pRegularFiles && S_ISREG(statBuf.st_mode)) {
271 FileInfo theFile(path, entryName,
false, statBuf.st_mtime);
273 if (matchesAllFilters(theFile.
getFullPath(), statBuf.st_mtime)) {
274 pRegularFiles->push_back(theFile);
281 std::vector<FileInfo>* pDirectories)
284 string canonicalPath = path;
291 vector<FileInfo> dirs;
300 pDirectories->insert(pDirectories->end(), dirs.begin(), dirs.end());
304 for (vector<FileInfo>::const_iterator it = dirs.begin(); it != dirs.end(); ++it) {
305 string subPath = canonicalPath +
"/" + it->basename();
306 BESDEBUG(_sDebugChannel,
"DirectoryUtil: recursing down to directory subtree=\"" << subPath <<
"\"..." << endl);
319 void DirectoryUtil::throwErrorForOpendirFail(
const string& fullPath)
323 string msg =
"Permission denied for some directory in path=\"" + fullPath +
"\"";
329 string msg =
"A symlink loop was detected in path=\"" + fullPath +
"\"";
335 string msg =
"A name in the path was too long. path=\"" + fullPath +
"\"";
341 string msg =
"Some part of the path was not found. path=\"" + fullPath +
"\"";
347 string msg =
"Some part of the path was not a directory. path=\"" + fullPath +
"\"";
353 string msg =
"Internal Error: Too many files are currently open!";
359 string msg =
"An unknown errno was found after opendir() was called on path=\"" + fullPath +
"\"";
365 bool DirectoryUtil::matchesAllFilters(
const std::string& path, time_t modTime)
const
369 if (!_suffix.empty() && !matchesSuffix(path, _suffix)) {
374 if (matches && _pRegExp) {
376 int numCharsMatching = _pRegExp->match(path.c_str(), path.size(), 0);
377 matches = (numCharsMatching > 0);
380 if (matches && _filteringModTimes) {
381 matches = (modTime < _newestModTime);
389 return (path.find(
"..") != string::npos);
395 string::size_type pos = path.find_last_not_of(
"/");
396 if (pos != string::npos) {
397 path = path.substr(0, pos + 1);
405 string::size_type pos = path.find_first_not_of(
"/");
406 path = path.substr(pos, string::npos);
412 std::ostringstream oss;
414 BESDEBUG(_sDebugChannel, oss.str() << endl);
419 for (vector<FileInfo>::const_iterator it = listing.begin(); it != listing.end(); ++it) {
420 os << it->toString() << endl;
438 bool DirectoryUtil::matchesSuffix(
const std::string& filename,
const std::string& suffix)
441 bool matches = (filename.find(suffix, filename.size() - suffix.size()) != string::npos);