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 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 = string(
"Excluded the item '").append(item_path).append(
"' from the catalog '").append(
get_catalog_name()).append(
"' node listing.");
349 string msg = string(
"Unable to create CatalogItem for '").append(
"' from the catalog '").append(
get_catalog_name()).append(
",' SKIPPING.");
351 BESDEBUG(MODULE, PROLOG << msg << endl);
391 throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
402 struct stat full_path_stat_buf;
403 int stat_result = stat(fullpath.c_str(), &full_path_stat_buf);
406 string(
"Unable to 'stat' the path '") + fullpath +
"' errno says: " + std::strerror(errno),
411 if(S_ISREG(full_path_stat_buf.st_mode)){
412 BESDEBUG(MODULE, PROLOG <<
"The requested node '"+fullpath+
"' is actually a leaf. Wut do?" << endl);
416 node->set_leaf(item);
419 string msg(__func__);
420 msg +=
"() - Failed to build CatalogItem for "+ path +
" BESCatlogDirectory::make_item() returned NULL.",
424 BESDEBUG(MODULE, PROLOG <<
"Actually, I'm a LEAF (" << (
void*)item <<
")" << endl);
427 else if(S_ISDIR(full_path_stat_buf.st_mode)){
428 BESDEBUG(MODULE, PROLOG <<
"Processing directory node: "<< fullpath << endl);
436 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
440 node->set_lmt(get_time(full_path_stat_buf.st_mtime));
442 dip = opendir(fullpath.c_str());
447 BESDEBUG(MODULE, PROLOG <<
"Unable to open '" << fullpath <<
"' SKIPPING (errno: " << std::strerror(errno) <<
")"<< endl);
452 while ((dit = readdir(dip)) != NULL) {
453 CatalogItem * item = make_item(fullpath, dit->d_name);
455 if(item->
get_type() == CatalogItem::node){
456 node->add_node(item);
459 node->add_leaf(item);
467 sort(node->nodes_begin(), node->nodes_end(), ordering);
468 sort(node->leaves_begin(), node->leaves_end(), ordering);
478 "A BESCatalogDirectory can only return nodes for directories and regular files. The path '" + path
479 +
"' is not a directory or a regular file for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
509 if (path[0] !=
'/')
throw BESInternalError(
"The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
519 string fullpath = rootdir + path;
521 DIR *dip = opendir(fullpath.c_str());
524 "A BESCatalogDirectory can only return nodes for directory. The path '" + path
525 +
"' is not a directory for BESCatalog '" +
get_catalog_name() +
"'.", __FILE__, __LINE__);
534 string(
"The path '") + path +
"' is not included in the catalog '" +
get_catalog_name() +
"'.",
541 int statret = stat(fullpath.c_str(), &buf);
543 node->set_lmt(get_time(buf.st_mtime));
546 while ((dit = readdir(dip)) != NULL) {
547 string item = dit->d_name;
548 if (item ==
"." || item ==
"..")
continue;
550 string item_path = fullpath +
"/" + item;
562 (void) lstat(item_path.c_str(), &lbuf);
563 if (S_ISLNK(lbuf.st_mode))
continue;
567 statret = stat(item_path.c_str(), &buf);
568 if (statret == 0 && S_ISDIR(buf.st_mode) && !
get_catalog_utils()->exclude(item)) {
571 node->add_item(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
573 node->add_node(
new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
575 else if (statret == 0 && S_ISREG(buf.st_mode) &&
get_catalog_utils()->include(item)) {
578 node->add_item(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
581 node->add_leaf(
new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
585 VERBOSE(
"Excluded the item '" << item_path <<
"' from the catalog '" <<
get_catalog_name() <<
"' node listing.");
593 sort(node->nodes_begin(), node->nodes_end(), ordering);
594 sort(node->leaves_begin(), node->leaves_end(), ordering);
625 ostream &out,
const string &path)
const
627 auto_ptr<CatalogNode> node(
get_node(path));
630 for (CatalogNode::item_citer i = node->items_begin(), e = node->items_end(); i != e; ++i) {
631 if ((*i)->get_type() == CatalogItem::leaf && (*i)->is_data()) {
632 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
634 else if ((*i)->get_type() == CatalogItem::node) {
635 get_site_map(prefix, leaf_suffix, out, path + (*i)->get_name() +
"/");
640 if (!node_suffix.empty())
641 out << prefix << path << node_suffix << endl;
644 for (CatalogNode::item_citer i = node->nodes_begin(), e = node->nodes_end(); i != e; ++i) {
645 assert((*i)->get_type() == CatalogItem::node);
646 get_site_map(prefix, node_suffix, leaf_suffix, out, path + (*i)->get_name() +
"/");
650 for (CatalogNode::item_citer i = node->leaves_begin(), e = node->leaves_end(); i != e; ++i) {
651 assert((*i)->get_type() == CatalogItem::leaf);
652 if ((*i)->is_data() && !leaf_suffix.empty())
653 out << prefix << path << (*i)->get_name() << leaf_suffix << endl;
666 strm << BESIndent::LMarg <<
"BESCatalogDirectory::dump - (" << (
void *)
this <<
")" << endl;
669 strm << BESIndent::LMarg <<
"catalog utilities: " << endl;
672 BESIndent::UnIndent();
673 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)