49#include "BESCatalogDirectory.h"
50#include "BESCatalogUtils.h"
51#include "BESCatalogEntry.h"
53#include "CatalogNode.h"
54#include "CatalogItem.h"
57#include "BESContainerStorageList.h"
58#include "BESFileContainerStorage.h"
61#include "BESInternalError.h"
62#include "BESForbiddenError.h"
63#include "BESNotFoundError.h"
71#define PROLOG "BESCatalogDirectory::" << __func__ << "() - "
93BESCatalogDirectory::~BESCatalogDirectory()
110 string use_node = node;
113 if (!node.empty() && node !=
"/") {
114 string::size_type pos = use_node.find_last_not_of(
"/");
115 use_node = use_node.substr(0, pos + 1);
120 if (use_node.empty()) use_node =
"/";
123 string fullnode = rootdir;
124 if (!use_node.empty()) {
130 fullnode = fullnode +
"/" + use_node;
134 string::size_type slash = fullnode.rfind(
"/");
135 if (slash != string::npos) {
136 basename = fullnode.substr(slash + 1, fullnode.size() - slash);
146 "BESCatalogDirectory::show_catalog: " <<
"use_node = " << use_node << endl <<
"rootdir = " << rootdir << endl <<
"fullnode = " << fullnode << endl <<
"basename = " << basename << endl);
160 entry->add_entry(myentry);
169 DIR *dip = opendir(fullnode.c_str());
170 if (dip !=
nullptr) {
177 string error =
"You do not have permission to view the node " + use_node;
185 bool dirs_only =
false;
198 BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
207 (void) lstat(fullnode.c_str(), &buf);
208 if (S_ISLNK(buf.st_mode)) {
209 string error =
"You do not have permission to access node " + use_node;
213 statret = stat(fullnode.c_str(), &buf);
214 if (statret == 0 && S_ISREG(buf.st_mode)) {
215 BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
217 list<string> services;
219 myentry->set_service_list(services);
221 else if (statret == 0) {
222 string error =
"You do not have permission to access " + use_node;
228 if (errno == ENOENT) {
229 string error =
"Node " + use_node +
" does not exist";
230 char *s_err = strerror(errno);
238 string error =
"Access denied for node " + use_node;
239 char *s_err = strerror(errno);
241 error = error + s_err;
248 string error =
"You do not have permission to access " + use_node;
275static string get_time(time_t the_time,
bool use_local_time =
false)
277 char buf[
sizeof "YYYY-MM-DDTHH:MM:SSzone"];
287 if (!use_local_time) {
288 gmtime_r(&the_time, &result);
289 status = strftime(buf,
sizeof buf,
"%FT%T%Z", &result);
292 localtime_r(&the_time, &result);
293 status = strftime(buf,
sizeof buf,
"%FT%T%Z", &result);
297 ERROR_LOG(
"Error getting last modified time time for a leaf item in BESCatalogDirectory.");
305CatalogItem *BESCatalogDirectory::make_item(
string path_prefix,
string item)
const
307 if (item ==
"." || item ==
"..")
311 BESDEBUG(MODULE, PROLOG <<
"Processing POSIX entry: " << item_path << endl);
316 BESDEBUG(MODULE, PROLOG <<
"catalog: " << this->
get_catalog_name() << endl);
317 BESDEBUG(MODULE, PROLOG <<
"include_item: " << (include_item?
"true":
"false") << endl);
318 BESDEBUG(MODULE, PROLOG <<
"exclude_item: " << (exclude_item?
"true":
"false") << endl);
330 (void) lstat(item_path.c_str(), &lbuf);
331 if (S_ISLNK(lbuf.st_mode))
336 int statret = stat(item_path.c_str(), &buf);
337 if (statret == 0 && S_ISDIR(buf.st_mode) && !exclude_item) {
338 BESDEBUG(MODULE, PROLOG << item_path <<
" is NODE" << endl);
339 return new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node);
341 else if (statret == 0 && S_ISREG(buf.st_mode) && include_item) {
342 BESDEBUG(MODULE, PROLOG << item_path <<
" is LEAF" << endl);
343 return new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
350 if(exclude_item || !include_item){
351 msg <<
"Excluded the item '" << item_path <<
"' from the catalog '" <<
355 msg <<
"Unable to create CatalogItem for '" << item_path <<
"' from the catalog '" <<
358 BESDEBUG(MODULE, PROLOG << msg.str());
398 throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
409 struct stat full_path_stat_buf;
410 int stat_result = stat(fullpath.c_str(), &full_path_stat_buf);
413 string(
"Unable to 'stat' the path '") + fullpath +
"' errno says: " + std::strerror(errno),
418 if(S_ISREG(full_path_stat_buf.st_mode)){
419 BESDEBUG(MODULE, PROLOG <<
"The requested node '"+fullpath+
"' is actually a leaf. Wut do?" << endl);
423 node->set_leaf(item);
426 string msg(__func__);
427 msg +=
"() - Failed to build CatalogItem for "+ path +
" BESCatlogDirectory::make_item() returned NULL.",
431 BESDEBUG(MODULE, PROLOG <<
"Actually, I'm a LEAF (" << (
void*)item <<
")" << endl);
434 else if(S_ISDIR(full_path_stat_buf.st_mode)){
435 BESDEBUG(MODULE, PROLOG <<
"Processing directory node: "<< fullpath << endl);
443 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
447 node->set_lmt(get_time(full_path_stat_buf.st_mtime));
449 dip = opendir(fullpath.c_str());
454 BESDEBUG(MODULE, PROLOG <<
"Unable to open '" << fullpath <<
"' SKIPPING (errno: " << std::strerror(errno) <<
")"<< endl);
459 while ((dit = readdir(dip)) != NULL) {
460 CatalogItem * item = make_item(fullpath, dit->d_name);
462 if(item->
get_type() == CatalogItem::node){
463 node->add_node(item);
466 node->add_leaf(item);
474 sort(node->nodes_begin(), node->nodes_end(), ordering);
475 sort(node->leaves_begin(), node->leaves_end(), ordering);
485 "A BESCatalogDirectory can only return nodes for directories and regular files. The path '" + path
486 +
"' is not a directory or a regular file for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
516 if (path[0] !=
'/')
throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
526 string fullpath = rootdir + path;
528 DIR *dip = opendir(fullpath.c_str());
531 "A BESCatalogDirectory can only return nodes for directory. The path '" + path
532 +
"' is not a directory for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
541 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
548 int statret = stat(fullpath.c_str(), &buf);
550 node->set_lmt(get_time(buf.st_mtime));
553 while ((dit = readdir(dip)) != NULL) {
554 string item = dit->d_name;
555 if (item ==
"." || item ==
"..")
continue;
557 string item_path = fullpath +
"/" + item;
569 (void) lstat(item_path.c_str(), &lbuf);
570 if (S_ISLNK(lbuf.st_mode))
continue;
574 statret = stat(item_path.c_str(), &buf);
575 if (statret == 0 && S_ISDIR(buf.st_mode) && !
get_catalog_utils()->exclude(item)) {
578 node->add_item(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
580 node->add_node(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
582 else if (statret == 0 && S_ISREG(buf.st_mode) &&
get_catalog_utils()->include(item)) {
585 node->add_item(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
588 node->add_leaf(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
592 VERBOSE(
"Excluded the item '" << item_path <<
"' from the catalog '" <<
get_catalog_name() <<
"' node listing.");
598 CatalogItem::CatalogItemAscending ordering;
600 sort(node->nodes_begin(), node->nodes_end(), ordering);
601 sort(node->leaves_begin(), node->leaves_end(), ordering);
632 ostream &out,
const string &path)
const
634 unique_ptr<CatalogNode> node(
get_node(path));
637 for (CatalogNode::item_citer i = node->items_begin(), e = node->items_end(); i != e; ++i) {
638 if ((*i)->get_type() == CatalogItem::leaf && (*i)->is_data()) {
639 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
641 else if ((*i)->get_type() == CatalogItem::node) {
642 get_site_map(prefix, leaf_suffix, out, path + (*i)->get_name() +
"/");
647 if (!node_suffix.empty())
648 out << prefix << path << node_suffix << endl;
651 for (CatalogNode::item_citer i = node->nodes_begin(), e = node->nodes_end(); i != e; ++i) {
652 assert((*i)->get_type() == CatalogItem::node);
653 get_site_map(prefix, node_suffix, leaf_suffix, out, path + (*i)->get_name() +
"/");
657 for (CatalogNode::item_citer i = node->leaves_begin(), e = node->leaves_end(); i != e; ++i) {
658 assert((*i)->get_type() == CatalogItem::leaf);
659 if ((*i)->is_data() && !leaf_suffix.empty())
660 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
673 strm << BESIndent::LMarg <<
"BESCatalogDirectory::dump - (" << (
void *)
this <<
")" << endl;
676 strm << BESIndent::LMarg <<
"catalog utilities: " << endl;
679 BESIndent::UnIndent();
680 BESIndent::UnIndent();
virtual bes::CatalogNode * get_node(const std::string &path) const
Get a CatalogNode for the given path in the current catalog.
virtual std::string get_root() const
Get the root directory for the catalog.
BESCatalogDirectory(const std::string &name)
A catalog for POSIX file systems.
virtual BESCatalogEntry * show_catalog(const std::string &container, BESCatalogEntry *entry)
Get the CatalogEntry for the given node.
virtual void get_site_map(const std::string &prefix, const std::string &node_suffix, const std::string &leaf_suffix, std::ostream &out, const std::string &path="/") const
Write the site map for this catalog to the stream.
virtual void dump(std::ostream &strm) const
dumps information about this object
const std::string & get_root_dir() const
Get the root directory of the catalog.
virtual bool exclude(const std::string &inQuestion) const
Should this file/directory be excluded in the catalog?
virtual unsigned int get_entries(DIR *dip, const std::string &fullnode, const std::string &use_node, BESCatalogEntry *entry, bool dirs_only)
virtual bool include(const std::string &inQuestion) const
Should this file/directory be included in the catalog?
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized for this catalog.
virtual std::string get_catalog_name() const
Get the name for this catalog.
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
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
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?
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
item_type get_type() const
Get the type of this item (unknown, node or leaf)