00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "config.h"
00034
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <dirent.h>
00038
00039 #include <cstring>
00040 #include <cerrno>
00041 #include <sstream>
00042
00043 using std::stringstream ;
00044 using std::endl ;
00045
00046 #include "BESCatalogDirectory.h"
00047 #include "BESCatalogUtils.h"
00048 #include "BESInfo.h"
00049 #include "BESResponseNames.h"
00050 #include "BESCatalogUtils.h"
00051 #include "BESContainerStorageList.h"
00052 #include "BESContainerStorageCatalog.h"
00053 #include "BESLog.h"
00054 #include "BESForbiddenError.h"
00055 #include "BESNotFoundError.h"
00056 #include "BESDebug.h"
00057
00058 void bes_add_stat_info( map<string,string> &props,
00059 struct stat &buf,
00060 const string &node ) ;
00061 void bes_get_stat_info( BESCatalogDirectory::bes_dir_entry &entry,
00062 struct stat &buf,
00063 const string &node);
00064
00065 BESCatalogDirectory::BESCatalogDirectory( const string &name )
00066 : BESCatalog( name )
00067 {
00068 _utils = BESCatalogUtils::Utils( name ) ;
00069 }
00070
00071 BESCatalogDirectory::~BESCatalogDirectory( )
00072 {
00073 }
00074
00075 void
00076 BESCatalogDirectory::show_catalog( const string &node,
00077 const string &coi,
00078 BESInfo *info )
00079 {
00080
00081 #if 0
00082
00083
00084 string use_node = node ;
00085 if( node != "" )
00086 {
00087 string::size_type stopat = node.length() - 1 ;
00088 while( node[stopat] == '/' )
00089 {
00090 stopat-- ;
00091 }
00092 use_node = use_node.substr( 0, stopat + 1 ) ;
00093 }
00094 #else
00095 string use_node = node;
00096
00097
00098 if (!node.empty() && node != "/") {
00099 string::size_type pos = use_node.find_last_not_of("/");
00100 use_node = use_node.substr(0, pos+1);
00101 }
00102
00103
00104
00105 if (use_node.empty())
00106 use_node = "/";
00107
00108 BESDEBUG("bes", "use_node: " << use_node << endl )
00109 #endif
00110 string rootdir = _utils->get_root_dir() ;
00111 string fullnode = rootdir ;
00112 if( !use_node.empty() )
00113 {
00114 fullnode = fullnode + "/" + use_node ;
00115 }
00116
00117 string basename ;
00118 string::size_type slash = fullnode.rfind( "/" ) ;
00119 if( slash != string::npos )
00120 {
00121 basename = fullnode.substr( slash+1, fullnode.length() - slash ) ;
00122 }
00123 else
00124 {
00125 basename = fullnode ;
00126 }
00127
00128
00129
00130
00131
00132 BESUtil::check_path( use_node, rootdir, _utils->follow_sym_links() ) ;
00133
00134
00135 DIR *dip = opendir( fullnode.c_str() ) ;
00136 if( dip != NULL )
00137 {
00138
00139
00140
00141
00142 if( _utils->exclude( basename ) )
00143 {
00144 closedir( dip ) ;
00145 string error = "You do not have permission to view the node "
00146 + use_node ;
00147 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00148 }
00149 struct stat cbuf ;
00150 int statret = stat( fullnode.c_str(), &cbuf ) ;
00151 int my_errno = errno ;
00152 if( statret == 0 )
00153 {
00154 map<string,string> props ;
00155 props["node"] = "true" ;
00156 props["catalog"] = get_catalog_name() ;
00157 if( use_node == "" )
00158 {
00159 bes_add_stat_info( props, cbuf, "/" ) ;
00160 }
00161 else
00162 {
00163 bes_add_stat_info( props, cbuf, use_node ) ;
00164 }
00165
00166 struct dirent *dit;
00167 unsigned int cnt = 0 ;
00168 struct stat buf;
00169 struct stat lbuf;
00170
00171 map<string,bes_dir_entry> dir_list ;
00172 while( ( dit = readdir( dip ) ) != NULL )
00173 {
00174 string dirEntry = dit->d_name ;
00175 if( dirEntry != "." && dirEntry != ".." )
00176 {
00177 string fullPath = fullnode + "/" + dirEntry ;
00178
00179
00180
00181
00182
00183
00184 bool continue_checking = true ;
00185 if( _utils->follow_sym_links() == false )
00186 {
00187 #if 0
00188 int lstatret = lstat( fullPath.c_str(), &lbuf ) ;
00189 #endif
00190 (void)lstat( fullPath.c_str(), &lbuf ) ;
00191 if( S_ISLNK( lbuf.st_mode ) )
00192 {
00193 continue_checking = false ;
00194 }
00195 }
00196
00197 if( continue_checking )
00198 {
00199
00200
00201
00202
00203 statret = stat( fullPath.c_str(), &buf ) ;
00204 if ( statret == 0 && S_ISDIR( buf.st_mode ) )
00205 {
00206 if( _utils->exclude( dirEntry ) == false )
00207 {
00208 cnt++ ;
00209 if( coi == CATALOG_RESPONSE )
00210 {
00211 bes_dir_entry entry ;
00212 entry.collection = true ;
00213 bes_get_stat_info( entry, buf, dirEntry ) ;
00214 dir_list[dirEntry] = entry ;
00215 }
00216 }
00217 }
00218 else if ( statret == 0 && S_ISREG( buf.st_mode ) )
00219 {
00220 if( _utils->include( dirEntry ) )
00221 {
00222 cnt++ ;
00223 if( coi == CATALOG_RESPONSE )
00224 {
00225 bes_dir_entry entry ;
00226 entry.collection = false ;
00227 isData( fullPath, entry.services ) ;
00228 bes_get_stat_info( entry, buf, dirEntry ) ;
00229 dir_list[dirEntry] = entry ;
00230 }
00231 }
00232 }
00233 }
00234 }
00235 }
00236 stringstream sscnt ;
00237 sscnt << cnt ;
00238 props["count"] = sscnt.str() ;
00239 info->begin_tag( "dataset", &props ) ;
00240
00241
00242
00243 if( coi == CATALOG_RESPONSE )
00244 {
00245 map<string,bes_dir_entry>::iterator i = dir_list.begin() ;
00246 map<string,bes_dir_entry>::iterator e = dir_list.end() ;
00247 for( ; i != e; i++ )
00248 {
00249 map<string,string> attrs ;
00250 if( (*i).second.collection )
00251 attrs["node"] = "true" ;
00252 else
00253 attrs["node"] = "false" ;
00254 attrs["catalog"] = get_catalog_name() ;
00255 attrs["name"] = (*i).second.name ;
00256 attrs["size"] = (*i).second.size ;
00257 string dt = (*i).second.mod_date + "T"
00258 + (*i).second.mod_time ;
00259 attrs["lastModified"] = dt ;
00260 info->begin_tag( "dataset", &attrs ) ;
00261
00262 list<string>::const_iterator si =
00263 (*i).second.services.begin() ;
00264 list<string>::const_iterator se =
00265 (*i).second.services.end() ;
00266 for( ; si != se; si++ )
00267 {
00268 info->add_tag( "serviceRef", (*si) ) ;
00269 }
00270 info->end_tag( "dataset" ) ;
00271 }
00272 }
00273 closedir( dip ) ;
00274 info->end_tag( "dataset" ) ;
00275 }
00276 else
00277 {
00278 closedir( dip ) ;
00279
00280 if( my_errno == ENOENT )
00281 {
00282 string error = "Node " + use_node + " does not exist" ;
00283 char *s_err = strerror( my_errno ) ;
00284 if( s_err )
00285 {
00286 error = s_err ;
00287 }
00288 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00289 }
00290
00291 else
00292 {
00293 string error = "Access denied for node " + use_node ;
00294 char *s_err = strerror( my_errno ) ;
00295 if( s_err )
00296 {
00297 error = error + s_err ;
00298 }
00299 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00300 }
00301 }
00302 }
00303 else
00304 {
00305
00306
00307 if( _utils->include( basename ) )
00308 {
00309 struct stat buf;
00310 int statret = 0 ;
00311 if( _utils->follow_sym_links() == false )
00312 {
00313 (void)lstat( fullnode.c_str(), &buf ) ;
00314 if( S_ISLNK( buf.st_mode ) )
00315 {
00316 string error = "You do not have permission to access node "
00317 + use_node ;
00318 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00319 }
00320 }
00321 statret = stat( fullnode.c_str(), &buf ) ;
00322 if ( statret == 0 && S_ISREG( buf.st_mode ) )
00323 {
00324 map<string,string> attrs ;
00325 attrs["node"] = "false" ;
00326 attrs["catalog"] = get_catalog_name() ;
00327 bes_add_stat_info( attrs, buf, node ) ;
00328 info->begin_tag( "dataset", &attrs ) ;
00329
00330 list<string> services ;
00331 isData( node, services ) ;
00332 list<string>::const_iterator si = services.begin() ;
00333 list<string>::const_iterator se = services.end() ;
00334 for( ; si != se; si++ )
00335 {
00336 info->add_tag( "serviceRef", (*si) ) ;
00337 }
00338
00339 info->end_tag( "dataset" ) ;
00340 }
00341 else if( statret == 0 )
00342 {
00343 string error = "You do not have permission to access "
00344 + use_node ;
00345 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00346 }
00347 else
00348 {
00349
00350
00351 if( errno == ENOENT )
00352 {
00353 string error = "Node " + use_node + " does not exist" ;
00354 char *s_err = strerror( errno ) ;
00355 if( s_err )
00356 {
00357 error = s_err ;
00358 }
00359 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00360 }
00361
00362 else
00363 {
00364 string error = "Access denied for node " + use_node ;
00365 char *s_err = strerror( errno ) ;
00366 if( s_err )
00367 {
00368 error = error + s_err ;
00369 }
00370 throw BESNotFoundError( error, __FILE__, __LINE__ ) ;
00371 }
00372 }
00373 }
00374 else
00375 {
00376 string error = "You do not have permission to access " + use_node ;
00377 throw BESForbiddenError( error, __FILE__, __LINE__ ) ;
00378 }
00379 }
00380 }
00381
00382 void
00383 bes_add_stat_info( map<string,string> &props,
00384 struct stat &buf,
00385 const string &node )
00386 {
00387 BESCatalogDirectory::bes_dir_entry entry ;
00388 bes_get_stat_info( entry, buf, node ) ;
00389 props["name"] = entry.name ;
00390 props["size"] = entry.size ;
00391 string dt = entry.mod_date + "T" + entry.mod_time ;
00392 props["lastModified"] = dt ;
00393 }
00394
00395 void
00396 bes_get_stat_info( BESCatalogDirectory::bes_dir_entry &entry,
00397 struct stat &buf, const string &node )
00398 {
00399 entry.name = node ;
00400
00401 off_t sz = buf.st_size ;
00402 stringstream ssz ;
00403 ssz << sz ;
00404 entry.size = ssz.str() ;
00405
00406
00407
00408 time_t mod = buf.st_mtime ;
00409 struct tm *stm = gmtime( &mod ) ;
00410 char mdate[64] ;
00411 strftime( mdate, 64, "%Y-%m-%d", stm ) ;
00412 char mtime[64] ;
00413 strftime( mtime, 64, "%T", stm ) ;
00414
00415 stringstream sdt ;
00416 sdt << mdate ;
00417 entry.mod_date = sdt.str() ;
00418
00419 stringstream stt ;
00420 stt << mtime ;
00421 entry.mod_time = stt.str() ;
00422 }
00423
00424 bool
00425 BESCatalogDirectory::isData( const string &inQuestion,
00426 list<string> &services )
00427 {
00428 BESContainerStorage *store =
00429 BESContainerStorageList::TheList()->find_persistence( get_catalog_name() ) ;
00430 if( !store )
00431 return false ;
00432
00433 BESContainerStorageCatalog *cat_store =
00434 dynamic_cast<BESContainerStorageCatalog *>( store ) ;
00435 if( !cat_store )
00436 return false ;
00437
00438 return cat_store->isData( inQuestion, services ) ;
00439 }
00440
00448 void
00449 BESCatalogDirectory::dump( ostream &strm ) const
00450 {
00451 strm << BESIndent::LMarg << "BESCatalogDirectory::dump - ("
00452 << (void *)this << ")" << endl ;
00453 BESIndent::Indent() ;
00454
00455 strm << BESIndent::LMarg << "catalog utilities: " << endl ;
00456 BESIndent::Indent() ;
00457 _utils->dump( strm ) ;
00458 BESIndent::UnIndent() ;
00459 BESIndent::UnIndent() ;
00460 }
00461