35 #include <sys/types.h>
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__ << "() - "
93 BESCatalogDirectory::~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.length() - 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());
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;
275 static string get_time(time_t the_time,
bool use_local_time =
false)
277 char buf[
sizeof "YYYY-MM-DDTHH:MM:SSzone"];
287 status = strftime(buf,
sizeof buf,
"%FT%T%Z", gmtime(&the_time));
289 status = strftime(buf,
sizeof buf,
"%FT%T%Z", localtime(&the_time));
292 ERROR_LOG(
"Error getting last modified time time for a leaf item in BESCatalogDirectory.");
300 CatalogItem *BESCatalogDirectory::make_item(
string path_prefix,
string item)
const
302 if (item ==
"." || item ==
"..")
306 BESDEBUG(MODULE, PROLOG <<
"Processing POSIX entry: " << item_path << endl);
311 BESDEBUG(MODULE, PROLOG <<
"catalog: " << this->
get_catalog_name() << endl);
312 BESDEBUG(MODULE, PROLOG <<
"include_item: " << (include_item?
"true":
"false") << endl);
313 BESDEBUG(MODULE, PROLOG <<
"exclude_item: " << (exclude_item?
"true":
"false") << endl);
325 (void) lstat(item_path.c_str(), &lbuf);
326 if (S_ISLNK(lbuf.st_mode))
331 int statret = stat(item_path.c_str(), &buf);
332 if (statret == 0 && S_ISDIR(buf.st_mode) && !exclude_item) {
333 BESDEBUG(MODULE, PROLOG << item_path <<
" is NODE" << endl);
334 return new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node);
336 else if (statret == 0 && S_ISREG(buf.st_mode) && include_item) {
337 BESDEBUG(MODULE, PROLOG << item_path <<
" is LEAF" << endl);
338 return new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
345 if(exclude_item || !include_item){
346 msg <<
"Excluded the item '" << item_path <<
"' from the catalog '" <<
350 msg <<
"Unable to create CatalogItem for '" << item_path <<
"' from the catalog '" <<
353 BESDEBUG(MODULE, PROLOG << msg.str());
393 throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
404 struct stat full_path_stat_buf;
405 int stat_result = stat(fullpath.c_str(), &full_path_stat_buf);
408 string(
"Unable to 'stat' the path '") + fullpath +
"' errno says: " + std::strerror(errno),
413 if(S_ISREG(full_path_stat_buf.st_mode)){
414 BESDEBUG(MODULE, PROLOG <<
"The requested node '"+fullpath+
"' is actually a leaf. Wut do?" << endl);
418 node->set_leaf(item);
421 string msg(__func__);
422 msg +=
"() - Failed to build CatalogItem for "+ path +
" BESCatlogDirectory::make_item() returned NULL.",
426 BESDEBUG(MODULE, PROLOG <<
"Actually, I'm a LEAF (" << (
void*)item <<
")" << endl);
429 else if(S_ISDIR(full_path_stat_buf.st_mode)){
430 BESDEBUG(MODULE, PROLOG <<
"Processing directory node: "<< fullpath << endl);
438 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
442 node->set_lmt(get_time(full_path_stat_buf.st_mtime));
444 dip = opendir(fullpath.c_str());
449 BESDEBUG(MODULE, PROLOG <<
"Unable to open '" << fullpath <<
"' SKIPPING (errno: " << std::strerror(errno) <<
")"<< endl);
454 while ((dit = readdir(dip)) != NULL) {
455 CatalogItem * item = make_item(fullpath, dit->d_name);
457 if(item->
get_type() == CatalogItem::node){
458 node->add_node(item);
461 node->add_leaf(item);
469 sort(node->nodes_begin(), node->nodes_end(), ordering);
470 sort(node->leaves_begin(), node->leaves_end(), ordering);
480 "A BESCatalogDirectory can only return nodes for directories and regular files. The path '" + path
481 +
"' is not a directory or a regular file for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
511 if (path[0] !=
'/')
throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
521 string fullpath = rootdir + path;
523 DIR *dip = opendir(fullpath.c_str());
526 "A BESCatalogDirectory can only return nodes for directory. The path '" + path
527 +
"' is not a directory for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
536 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
543 int statret = stat(fullpath.c_str(), &buf);
545 node->set_lmt(get_time(buf.st_mtime));
548 while ((dit = readdir(dip)) != NULL) {
549 string item = dit->d_name;
550 if (item ==
"." || item ==
"..")
continue;
552 string item_path = fullpath +
"/" + item;
564 (void) lstat(item_path.c_str(), &lbuf);
565 if (S_ISLNK(lbuf.st_mode))
continue;
569 statret = stat(item_path.c_str(), &buf);
570 if (statret == 0 && S_ISDIR(buf.st_mode) && !
get_catalog_utils()->exclude(item)) {
573 node->add_item(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
575 node->add_node(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
577 else if (statret == 0 && S_ISREG(buf.st_mode) &&
get_catalog_utils()->include(item)) {
580 node->add_item(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
583 node->add_leaf(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
587 VERBOSE(
"Excluded the item '" << item_path <<
"' from the catalog '" <<
get_catalog_name() <<
"' node listing.");
595 sort(node->nodes_begin(), node->nodes_end(), ordering);
596 sort(node->leaves_begin(), node->leaves_end(), ordering);
627 ostream &out,
const string &path)
const
629 auto_ptr<CatalogNode> node(
get_node(path));
632 for (CatalogNode::item_citer i = node->items_begin(), e = node->items_end(); i != e; ++i) {
633 if ((*i)->get_type() == CatalogItem::leaf && (*i)->is_data()) {
634 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
636 else if ((*i)->get_type() == CatalogItem::node) {
637 get_site_map(prefix, leaf_suffix, out, path + (*i)->get_name() +
"/");
642 if (!node_suffix.empty())
643 out << prefix << path << node_suffix << endl;
646 for (CatalogNode::item_citer i = node->nodes_begin(), e = node->nodes_end(); i != e; ++i) {
647 assert((*i)->get_type() == CatalogItem::node);
648 get_site_map(prefix, node_suffix, leaf_suffix, out, path + (*i)->get_name() +
"/");
652 for (CatalogNode::item_citer i = node->leaves_begin(), e = node->leaves_end(); i != e; ++i) {
653 assert((*i)->get_type() == CatalogItem::leaf);
654 if ((*i)->is_data() && !leaf_suffix.empty())
655 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
668 strm << BESIndent::LMarg <<
"BESCatalogDirectory::dump - (" << (
void *)
this <<
")" << endl;
671 strm << BESIndent::LMarg <<
"catalog utilities: " << endl;
674 BESIndent::UnIndent();
675 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
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?
const std::string & get_root_dir() const
Get the root directory of the catalog.
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Catalogs provide a hierarchical organization for data.
virtual std::string get_catalog_name() const
Get the name for this catalog.
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized 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()
static void check_path(const std::string &path, const std::string &root, bool follow_sym_links)
Check if the specified path is valid.
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)