bes  Updated for version 3.17.0
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 #include <sstream>
42 
43 using std::stringstream;
44 using std::endl;
45 
46 #include "BESCatalogDirectory.h"
47 #include "BESCatalogUtils.h"
48 #include "BESCatalogEntry.h"
49 #include "BESInfo.h"
50 #include "BESCatalogUtils.h"
51 #include "BESContainerStorageList.h"
52 #include "BESContainerStorageCatalog.h"
53 #include "BESLog.h"
54 #include "BESForbiddenError.h"
55 #include "BESNotFoundError.h"
56 #include "BESDebug.h"
57 
58 BESCatalogDirectory::BESCatalogDirectory(const string &name) :
59  BESCatalog(name)
60 {
61  _utils = BESCatalogUtils::Utils(name);
62 }
63 
64 BESCatalogDirectory::~BESCatalogDirectory()
65 {
66 }
67 
69 BESCatalogDirectory::show_catalog(const string &node, const string &coi, BESCatalogEntry *entry)
70 {
71  string use_node = node;
72  // use_node should only end in '/' is that's the only character in which
73  // case there's no need to call find()
74  if (!node.empty() && node != "/") {
75  string::size_type pos = use_node.find_last_not_of("/");
76  use_node = use_node.substr(0, pos + 1);
77  }
78 
79  // This takes care of bizarre cases like "///" where use_node would be
80  // empty after the substring call.
81  if (use_node.empty())
82  use_node = "/";
83 
84  string rootdir = _utils->get_root_dir();
85  string fullnode = rootdir;
86  if (!use_node.empty()) {
87  fullnode = fullnode + "/" + use_node;
88  }
89 
90  string basename;
91  string::size_type slash = fullnode.rfind("/");
92  if (slash != string::npos) {
93  basename = fullnode.substr(slash + 1, fullnode.length() - slash);
94  }
95  else {
96  basename = fullnode;
97  }
98 
99  BESDEBUG( "bes", "BESCatalogDirectory::show_catalog: "
100  << "use_node = " << use_node << endl
101  << "rootdir = " << rootdir << endl
102  << "fullnode = " << fullnode << endl
103  << "basename = " << basename << endl );
104 
105  // This will throw the appropriate exception (Forbidden or Not Found).
106  // Checks to make sure the different elements of the path are not
107  // symbolic links if follow_sym_links is set to false, and checks to
108  // make sure have permission to access node and the node exists.
109  BESUtil::check_path(use_node, rootdir, _utils->follow_sym_links());
110 
111  BESCatalogEntry *myentry = new BESCatalogEntry(use_node, get_catalog_name());
112  if (entry) {
113  // if an entry was passed, then add this one to it
114  entry->add_entry(myentry);
115  }
116  else {
117  // else we want to return the new entry created
118  entry = myentry;
119  }
120 
121  // Is this node a directory?
122  DIR *dip = opendir(fullnode.c_str());
123  if (dip != NULL) {
124  try {
125  // The node is a directory
126 
127  // if the directory requested is in the exclude list then we won't
128  // let the user see it.
129  if (_utils->exclude(basename)) {
130  string error = "You do not have permission to view the node " + use_node;
131  throw BESForbiddenError(error, __FILE__, __LINE__);
132  }
133 
134  bool dirs_only = false;
135  _utils->get_entries(dip, fullnode, use_node, coi, myentry, dirs_only);
136  } catch (... /*BESError &e */) {
137  closedir(dip);
138  throw /* e */;
139  }
140  closedir(dip);
141 
142  BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
143  }
144  else {
145  // if the node is not in the include list then the requester does
146  // not have access to that node
147  if (_utils->include(basename)) {
148  struct stat buf;
149  int statret = 0;
150  if (_utils->follow_sym_links() == false) {
151  /*statret =*/(void) lstat(fullnode.c_str(), &buf);
152  if (S_ISLNK(buf.st_mode)) {
153  string error = "You do not have permission to access node " + use_node;
154  throw BESForbiddenError(error, __FILE__, __LINE__);
155  }
156  }
157  statret = stat(fullnode.c_str(), &buf);
158  if (statret == 0 && S_ISREG(buf.st_mode)) {
159  BESCatalogUtils::bes_add_stat_info(myentry, fullnode);
160 
161  list < string > services;
162  BESCatalogUtils::isData(node, get_catalog_name(), services);
163  myentry->set_service_list(services);
164  }
165  else if (statret == 0) {
166  string error = "You do not have permission to access " + use_node;
167  throw BESForbiddenError(error, __FILE__, __LINE__);
168  }
169  else {
170  // ENOENT means that the path or part of the path does not
171  // exist
172  if (errno == ENOENT) {
173  string error = "Node " + use_node + " does not exist";
174  char *s_err = strerror(errno);
175  if (s_err) {
176  error = s_err;
177  }
178  throw BESNotFoundError(error, __FILE__, __LINE__);
179  }
180  // any other error means that access is denied for some reason
181  else {
182  string error = "Access denied for node " + use_node;
183  char *s_err = strerror(errno);
184  if (s_err) {
185  error = error + s_err;
186  }
187  throw BESNotFoundError(error, __FILE__, __LINE__);
188  }
189  }
190  }
191  else {
192  string error = "You do not have permission to access " + use_node;
193  throw BESForbiddenError(error, __FILE__, __LINE__);
194  }
195  }
196 
197  return entry;
198 }
199 
207 void BESCatalogDirectory::dump(ostream &strm) const
208 {
209  strm << BESIndent::LMarg << "BESCatalogDirectory::dump - (" << (void *) this << ")" << endl;
210  BESIndent::Indent();
211 
212  strm << BESIndent::LMarg << "catalog utilities: " << endl;
213  BESIndent::Indent();
214  _utils->dump(strm);
215  BESIndent::UnIndent();
216  BESIndent::UnIndent();
217 }
218 
error thrown if the resource requested cannot be found
virtual void dump(ostream &strm) const
dumps information about this object
abstract base class catalog object. Derived classes know how to show nodes and leaves in a catalog...
Definition: BESCatalog.h:47
error thrown if the BES is not allowed to access the resource requested
static void check_path(const string &path, const string &root, bool follow_sym_links)
Definition: BESUtil.cc:237