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