bes  Updated for version 3.20.6
BESCatalogDirectory.cc
1 // BESCatalogDirectory.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include "config.h"
34 
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
38 
39 #include <cstring>
40 #include <cerrno>
41 
42 #include <sstream>
43 #include <cassert>
44 
45 #include <memory>
46 #include <algorithm>
47 
48 #include "BESUtil.h"
49 #include "BESCatalogDirectory.h"
50 #include "BESCatalogUtils.h"
51 #include "BESCatalogEntry.h"
52 
53 #include "CatalogNode.h"
54 #include "CatalogItem.h"
55 
56 #include "BESInfo.h"
57 #include "BESContainerStorageList.h"
58 #include "BESFileContainerStorage.h"
59 #include "BESLog.h"
60 
61 #include "BESInternalError.h"
62 #include "BESForbiddenError.h"
63 #include "BESNotFoundError.h"
64 
65 #include "BESDebug.h"
66 
67 using namespace bes;
68 using namespace std;
69 
70 #define MODULE "bes"
71 #define PROLOG "BESCatalogDirectory::" << __func__ << "() - "
72 
86  BESCatalog(name)
87 {
88 #if 0
89  get_catalog_utils() = BESCatalogUtils::Utils(name);
90 #endif
91 }
92 
93 BESCatalogDirectory::~BESCatalogDirectory()
94 {
95 }
96 
109 {
110  string use_node = node;
111  // use_node should only end in '/' if that's the only character in which
112  // case there's no need to call find()
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);
116  }
117 
118  // This takes care of bizarre cases like "///" where use_node would be
119  // empty after the substring call.
120  if (use_node.empty()) use_node = "/";
121 
122  string rootdir = get_catalog_utils()->get_root_dir();
123  string fullnode = rootdir;
124  if (!use_node.empty()) {
125  // TODO It's hard to know just what this code is supposed to do, but I
126  // think the following can be an error. Above, if use_node is empty(), the use_node becomes
127  // "/" and then it's not empty() and fullnode becomes "<stuff>//" but we just
128  // jumped through all kinds of hoops to make sure there was either zero
129  // or one trailing slash. jhrg 2.26.18
130  fullnode = fullnode + "/" + use_node;
131  }
132 
133  string basename;
134  string::size_type slash = fullnode.rfind("/");
135  if (slash != string::npos) {
136  basename = fullnode.substr(slash + 1, fullnode.length() - slash);
137  }
138  else {
139  basename = fullnode;
140  }
141 
142  // fullnode is the full pathname of the node, including the 'root' pathanme
143  // basename is the last component of fullnode
144 
145  BESDEBUG(MODULE,
146  "BESCatalogDirectory::show_catalog: " << "use_node = " << use_node << endl << "rootdir = " << rootdir << endl << "fullnode = " << fullnode << endl << "basename = " << basename << endl);
147 
148  // This will throw the appropriate exception (Forbidden or Not Found).
149  // Checks to make sure the different elements of the path are not
150  // symbolic links if follow_sym_links is set to false, and checks to
151  // make sure have permission to access node and the node exists.
152  // TODO Move up; this can be done once use_node is set. jhrg 2.26.18
153  BESUtil::check_path(use_node, rootdir, get_catalog_utils()->follow_sym_links());
154 
155  // If null is passed in, then return the new entry, else add the new entry to the
156  // existing Entry object. jhrg 2.26.18
157  BESCatalogEntry *myentry = new BESCatalogEntry(use_node, get_catalog_name());
158  if (entry) {
159  // if an entry was passed, then add this one to it
160  entry->add_entry(myentry);
161  }
162  else {
163  // else we want to return the new entry created
164  entry = myentry;
165  }
166 
167  // Is this node a directory?
168  // TODO use stat() instead. jhrg 2.26.18
169  DIR *dip = opendir(fullnode.c_str());
170  if (dip != NULL) {
171  try {
172  // The node is a directory
173 
174  // if the directory requested is in the exclude list then we won't
175  // let the user see it.
176  if (get_catalog_utils()->exclude(basename)) {
177  string error = "You do not have permission to view the node " + use_node;
178  throw BESForbiddenError(error, __FILE__, __LINE__);
179  }
180 
181  // Now that we are ready to start building the response data we
182  // cancel any pending timeout alarm according to the configuration.
184 
185  bool dirs_only = false;
186  // TODO This is the only place in the code where get_entries() is called
187  // jhrg 2.26.18
188  get_catalog_utils()->get_entries(dip, fullnode, use_node, myentry, dirs_only);
189  }
190  catch (... /*BESError &e */) {
191  closedir(dip);
192  throw /* e */;
193  }
194  closedir(dip);
195 
196  // TODO This is the only place this method is called. replace the static method
197  // with an object call (i.e., get_catalog_utils())? jhrg 2.26.18
198  BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
199  }
200  else {
201  // if the node is not in the include list then the requester does
202  // not have access to that node
203  if (get_catalog_utils()->include(basename)) {
204  struct stat buf;
205  int statret = 0;
206  if (get_catalog_utils()->follow_sym_links() == false) {
207  /*statret =*/(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;
210  throw BESForbiddenError(error, __FILE__, __LINE__);
211  }
212  }
213  statret = stat(fullnode.c_str(), &buf);
214  if (statret == 0 && S_ISREG(buf.st_mode)) {
215  BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
216 
217  list<string> services;
218  BESCatalogUtils::isData(node, get_catalog_name(), services);
219  myentry->set_service_list(services);
220  }
221  else if (statret == 0) {
222  string error = "You do not have permission to access " + use_node;
223  throw BESForbiddenError(error, __FILE__, __LINE__);
224  }
225  else {
226  // ENOENT means that the path or part of the path does not
227  // exist
228  if (errno == ENOENT) {
229  string error = "Node " + use_node + " does not exist";
230  char *s_err = strerror(errno);
231  if (s_err) {
232  error = s_err;
233  }
234  throw BESNotFoundError(error, __FILE__, __LINE__);
235  }
236  // any other error means that access is denied for some reason
237  else {
238  string error = "Access denied for node " + use_node;
239  char *s_err = strerror(errno);
240  if (s_err) {
241  error = error + s_err;
242  }
243  throw BESNotFoundError(error, __FILE__, __LINE__);
244  }
245  }
246  }
247  else {
248  string error = "You do not have permission to access " + use_node;
249  throw BESForbiddenError(error, __FILE__, __LINE__);
250  }
251  }
252 
253  return entry;
254 }
255 
261 string
263 {
264  return get_catalog_utils()->get_root_dir();
265 }
266 
275 static string get_time(time_t the_time, bool use_local_time = false)
276 {
277  char buf[sizeof "YYYY-MM-DDTHH:MM:SSzone"];
278  int status = 0;
279 
280  // From StackOverflow:
281  // This will work too, if your compiler doesn't support %F or %T:
282  // strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%Z", gmtime(&now));
283  //
284  // Apologies for the twisted logic - UTC is the default. Override to
285  // local time using BES.LogTimeLocal=yes in bes.conf. jhrg 11/15/17
286  if (!use_local_time)
287  status = strftime(buf, sizeof buf, "%FT%T%Z", gmtime(&the_time));
288  else
289  status = strftime(buf, sizeof buf, "%FT%T%Z", localtime(&the_time));
290 
291  if (!status)
292  LOG("Error getting last modified time time for a leaf item in BESCatalogDirectory.");
293 
294  return buf;
295 }
296 
300 CatalogItem *BESCatalogDirectory::make_item(string path_prefix, string item) const
301 {
302  if (item == "." || item == "..")
303  return 0;
304 
305  string item_path = BESUtil::assemblePath(path_prefix,item);
306  BESDEBUG(MODULE, PROLOG << "Processing POSIX entry: " << item_path << endl);
307 
308  bool include_item = get_catalog_utils()->include(item);
309  bool exclude_item = get_catalog_utils()->exclude(item);
310 
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);
314 
315  // TODO add a test in configure for the readdir macro(s) DT_REG, DT_LNK
316  // and DT_DIR and use those, if present, to dßetermine if the name is a
317  // link, directory or regular file. These are not present on all systems.
318  // Also, since we need mtime, these are not a huge time saver. But if we
319  // decide not to use the mtime, using these macros could save lots of system
320  // calls. jhrg 3/9/18
321 
322  // Skip this dir entry if it is a sym link and follow links is false
323  if (get_catalog_utils()->follow_sym_links() == false) {
324  struct stat lbuf;
325  (void) lstat(item_path.c_str(), &lbuf);
326  if (S_ISLNK(lbuf.st_mode))
327  return 0;
328  }
329  // Is this a directory or a file? Should it be excluded or included?
330  struct stat buf;
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);
335  }
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),
339  get_catalog_utils()->is_data(item), CatalogItem::leaf);
340  }
341 
342  // This is the error case; it only is run when the item_path is neither a
343  // directory nor a regular file.
344  string msg;
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.");
347  }
348  else {
349  string msg = string("Unable to create CatalogItem for '").append("' from the catalog '").append(get_catalog_name()).append(",' SKIPPING.");
350  }
351  BESDEBUG(MODULE, PROLOG << msg << endl);
352  VERBOSE(msg);
353 
354  return 0;
355 }
356 
357 // path must start with a '/'. By this class it will be interpreted as a
358 // starting at the CatalogDirectory instance's root directory. It may either
359 // end in a '/' or not.
360 //
361 // If it is not a directory - that is an error. (return null or throw?)
362 //
363 // Item names are relative
364 
387 CatalogNode *
388 BESCatalogDirectory::get_node(const string &path) const
389 {
390  if (path[0] != '/')
391  throw BESInternalError("The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
392 
393  string rootdir = get_catalog_utils()->get_root_dir();
394 
395  // This will throw the appropriate exception (Forbidden or Not Found).
396  // Checks to make sure the different elements of the path are not
397  // symbolic links if follow_sym_links is set to false, and checks to
398  // make sure have permission to access node and the node exists.
399  // TODO Make BESUtil::check_path() return the stat struct so we don't have to stat again here.
400  BESUtil::check_path(path, rootdir, get_catalog_utils()->follow_sym_links());
401  string fullpath = BESUtil::assemblePath(rootdir, path);
402  struct stat full_path_stat_buf;
403  int stat_result = stat(fullpath.c_str(), &full_path_stat_buf);
404  if(stat_result){
405  throw BESForbiddenError(
406  string("Unable to 'stat' the path '") + fullpath + "' errno says: " + std::strerror(errno),
407  __FILE__, __LINE__);
408  }
409 
410  CatalogNode *node = new CatalogNode(path);
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);
413 
414  CatalogItem *item = make_item(rootdir, path);
415  if(item){
416  node->set_leaf(item);
417  }
418  else {
419  string msg(__func__);
420  msg += "() - Failed to build CatalogItem for "+ path + " BESCatlogDirectory::make_item() returned NULL.",
421  throw BESInternalError(msg,__FILE__, __LINE__);
422  }
423 
424  BESDEBUG(MODULE, PROLOG << "Actually, I'm a LEAF (" << (void*)item << ")" << endl);
425  return node;
426  }
427  else if(S_ISDIR(full_path_stat_buf.st_mode)){
428  BESDEBUG(MODULE, PROLOG << "Processing directory node: "<< fullpath << endl);
429  DIR *dip = 0;
430  try {
431  // The node is a directory
432  // Based on other code (show_catalogs()), use BESCatalogUtils::exclude() on
433  // a directory, but BESCatalogUtils::include() on a file.
434  if (get_catalog_utils()->exclude(path))
435  throw BESForbiddenError(
436  string("The path '") + path + "' is not included in the catalog '" + get_catalog_name() + "'.",
437  __FILE__, __LINE__);
438 
439  node->set_catalog_name(get_catalog_name());
440  node->set_lmt(get_time(full_path_stat_buf.st_mtime));
441 
442  dip = opendir(fullpath.c_str());
443  if(dip == NULL){
444  // That went well...
445  // We need to return this "node", and at this point it is empty.
446  // Which is probably enough, so we do nothing more.
447  BESDEBUG(MODULE, PROLOG << "Unable to open '" << fullpath << "' SKIPPING (errno: " << std::strerror(errno) << ")"<< endl);
448  }
449  else {
450  // otherwise we grind through the node contents...
451  struct dirent *dit;
452  while ((dit = readdir(dip)) != NULL) {
453  CatalogItem * item = make_item(fullpath, dit->d_name);
454  if(item){
455  if(item->get_type() == CatalogItem::node){
456  node->add_node(item);
457  }
458  else {
459  node->add_leaf(item);
460  }
461  }
462  }
463  closedir(dip);
464  }
465 
467  sort(node->nodes_begin(), node->nodes_end(), ordering);
468  sort(node->leaves_begin(), node->leaves_end(), ordering);
469 
470  return node;
471  }
472  catch (...) {
473  closedir(dip);
474  throw;
475  }
476  }
477  throw BESInternalError(
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__);
480 }
481 
482 #if 0
483 // path must start with a '/'. By this class it will be interpreted as a
484 // starting at the CatalogDirectory instance's root directory. It may either
485 // end in a '/' or not.
486 //
487 // If it is not a directory - that is an error. (return null or throw?)
488 //
489 // Item names are relative
490 
506 CatalogNode *
507 BESCatalogDirectory::get_node(const string &path) const
508 {
509  if (path[0] != '/') throw BESInternalError("The path sent to BESCatalogDirectory::get_node() must start with a slash (/)", __FILE__, __LINE__);
510 
511  string rootdir = get_catalog_utils()->get_root_dir();
512 
513  // This will throw the appropriate exception (Forbidden or Not Found).
514  // Checks to make sure the different elements of the path are not
515  // symbolic links if follow_sym_links is set to false, and checks to
516  // make sure have permission to access node and the node exists.
517  BESUtil::check_path(path, rootdir, get_catalog_utils()->follow_sym_links());
518 
519  string fullpath = rootdir + path;
520 
521  DIR *dip = opendir(fullpath.c_str());
522  if (!dip)
523  throw BESInternalError(
524  "A BESCatalogDirectory can only return nodes for directory. The path '" + path
525  + "' is not a directory for BESCatalog '" + get_catalog_name() + "'.", __FILE__, __LINE__);
526 
527  try {
528  // The node is a directory
529 
530  // Based on other code (show_catalogs()), use BESCatalogUtils::exclude() on
531  // a directory, but BESCatalogUtils::include() on a file.
532  if (get_catalog_utils()->exclude(path))
533  throw BESForbiddenError(
534  string("The path '") + path + "' is not included in the catalog '" + get_catalog_name() + "'.",
535  __FILE__, __LINE__);
536 
537  CatalogNode *node = new CatalogNode(path);
538 
539  node->set_catalog_name(get_catalog_name());
540  struct stat buf;
541  int statret = stat(fullpath.c_str(), &buf);
542  if (statret == 0 /* && S_ISDIR(buf.st_mode) */)
543  node->set_lmt(get_time(buf.st_mtime));
544 
545  struct dirent *dit;
546  while ((dit = readdir(dip)) != NULL) {
547  string item = dit->d_name;
548  if (item == "." || item == "..") continue;
549 
550  string item_path = fullpath + "/" + item;
551 
552  // TODO add a test in configure for the readdir macro(s) DT_REG, DT_LNK
553  // and DT_DIR and use those, if present, to determine if the name is a
554  // link, directory or regular file. These are not present on all systems.
555  // Also, since we need mtime, these are not a huge time saver. But if we
556  // decide not to use the mtime, using these macros could save lots of system
557  // calls. jhrg 3/9/18
558 
559  // Skip this dir entry if it is a sym link and follow links is false
560  if (get_catalog_utils()->follow_sym_links() == false) {
561  struct stat lbuf;
562  (void) lstat(item_path.c_str(), &lbuf);
563  if (S_ISLNK(lbuf.st_mode)) continue;
564  }
565 
566  // Is this a directory or a file? Should it be excluded or included?
567  statret = stat(item_path.c_str(), &buf);
568  if (statret == 0 && S_ISDIR(buf.st_mode) && !get_catalog_utils()->exclude(item)) {
569 #if 0
570  // Add a new node; set the size to zero.
571  node->add_item(new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
572 #endif
573  node->add_node(new CatalogItem(item, 0, get_time(buf.st_mtime), CatalogItem::node));
574  }
575  else if (statret == 0 && S_ISREG(buf.st_mode) && get_catalog_utils()->include(item)) {
576 #if 0
577  // Add a new leaf.
578  node->add_item(new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
579  get_catalog_utils()->is_data(item), CatalogItem::leaf));
580 #endif
581  node->add_leaf(new CatalogItem(item, buf.st_size, get_time(buf.st_mtime),
582  get_catalog_utils()->is_data(item), CatalogItem::leaf));
583  }
584  else {
585  VERBOSE("Excluded the item '" << item_path << "' from the catalog '" << get_catalog_name() << "' node listing.");
586  }
587  } // end of the while loop
588 
589  closedir(dip);
590 
592 
593  sort(node->nodes_begin(), node->nodes_end(), ordering);
594  sort(node->leaves_begin(), node->leaves_end(), ordering);
595 
596  return node;
597  }
598  catch (...) {
599  closedir(dip);
600  throw;
601  }
602 }
603 #endif
604 
624 void BESCatalogDirectory::get_site_map(const string &prefix, const string &node_suffix, const string &leaf_suffix,
625  ostream &out, const string &path) const
626 {
627  auto_ptr<CatalogNode> node(get_node(path));
628 
629 #if ITEMS
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;
633  }
634  else if ((*i)->get_type() == CatalogItem::node) {
635  get_site_map(prefix, leaf_suffix, out, path + (*i)->get_name() + "/");
636  }
637  }
638 #endif
639 
640  if (!node_suffix.empty())
641  out << prefix << path << node_suffix << endl;
642 
643  // Depth-first node traversal. Assume the nodes and leaves are sorted
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() + "/");
647  }
648 
649  // For leaves, only write the data items
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;
654  }
655 }
656 
664 void BESCatalogDirectory::dump(ostream &strm) const
665 {
666  strm << BESIndent::LMarg << "BESCatalogDirectory::dump - (" << (void *) this << ")" << endl;
667  BESIndent::Indent();
668 
669  strm << BESIndent::LMarg << "catalog utilities: " << endl;
670  BESIndent::Indent();
671  get_catalog_utils()->dump(strm);
672  BESIndent::UnIndent();
673  BESIndent::UnIndent();
674 }
675 
BESCatalogUtils::dump
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Definition: BESCatalogUtils.cc:506
BESCatalogUtils::include
virtual bool include(const std::string &inQuestion) const
Should this file/directory be included in the catalog?
Definition: BESCatalogUtils.cc:183
BESCatalogDirectory::show_catalog
virtual BESCatalogEntry * show_catalog(const std::string &container, BESCatalogEntry *entry)
Get the CatalogEntry for the given node.
Definition: BESCatalogDirectory.cc:108
BESNotFoundError
error thrown if the resource requested cannot be found
Definition: BESNotFoundError.h:40
BESCatalogUtils::exclude
virtual bool exclude(const std::string &inQuestion) const
Should this file/directory be excluded in the catalog?
Definition: BESCatalogUtils.cc:234
bes::CatalogItem::CatalogItemAscending
Definition: CatalogItem.h:128
BESUtil::check_path
static void check_path(const std::string &path, const std::string &root, bool follow_sym_links)
Check if the specified path is valid.
Definition: BESUtil.cc:254
BESUtil::conditional_timeout_cancel
static void conditional_timeout_cancel()
Definition: BESUtil.cc:967
BESCatalog::get_catalog_name
virtual std::string get_catalog_name() const
Get the name for this catalog.
Definition: BESCatalog.h:103
BESCatalogDirectory::get_node
virtual bes::CatalogNode * get_node(const std::string &path) const
Get a CatalogNode for the given path in the current catalog.
Definition: BESCatalogDirectory.cc:388
BESCatalogDirectory::get_site_map
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.
Definition: BESCatalogDirectory.cc:624
BESUtil::assemblePath
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.
Definition: BESUtil.cc:821
bes::CatalogItem::get_type
item_type get_type() const
Get the type of this item (unknown, node or leaf)
Definition: CatalogItem.h:153
BESCatalogDirectory::BESCatalogDirectory
BESCatalogDirectory(const std::string &name)
A catalog for POSIX file systems.
Definition: BESCatalogDirectory.cc:85
bes::CatalogNode
Definition: CatalogNode.h:45
bes::CatalogItem
Definition: CatalogItem.h:72
BESCatalogUtils::get_entries
virtual unsigned int get_entries(DIR *dip, const std::string &fullnode, const std::string &use_node, BESCatalogEntry *entry, bool dirs_only)
Definition: BESCatalogUtils.cc:287
BESForbiddenError
error thrown if the BES is not allowed to access the resource requested
Definition: BESForbiddenError.h:40
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
BESCatalog::get_catalog_utils
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized for this catalog.
Definition: BESCatalog.h:113
BESCatalogEntry
Definition: BESCatalogEntry.h:46
BESCatalogUtils::get_root_dir
const std::string & get_root_dir() const
Get the root directory of the catalog.
Definition: BESCatalogUtils.h:102
BESCatalog
Catalogs provide a hierarchical organization for data.
Definition: BESCatalog.h:51
BESCatalogDirectory::get_root
virtual std::string get_root() const
Get the root directory for the catalog.
Definition: BESCatalogDirectory.cc:262
BESCatalogDirectory::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESCatalogDirectory.cc:664