Gaudi Framework, version v20r2

Generated: 18 Jul 2008

PathResolver.cpp

Go to the documentation of this file.
00001 // $Header: /local/reps/Gaudi/GaudiKernel/src/Lib/PathResolver.cpp,v 1.6 2007/02/27 13:44:11 hmd Exp $
00002 #include "GaudiKernel/PathResolver.h"
00003 
00004 #include <cstdlib>
00005 #include <cstdio>
00006 
00007 #include <iostream>
00008 #include <vector>
00009 
00010 #include <sys/stat.h>
00011 
00012 #ifdef _WIN32
00013 #define stat _stat
00014 #include <direct.h>
00015 #include <io.h>
00016 #else
00017 #include <unistd.h>
00018 #include <dirent.h>
00019 #endif
00020 
00021 namespace System {
00022 
00023 typedef enum
00024   {
00025     PR_regular_file,
00026     PR_directory
00027   } PR_file_type;
00028 
00029 typedef enum {
00030   PR_local,
00031   PR_recursive } PR_search_type;
00032 
00033 static void PR_compress_path (std::string& dir)
00034 {
00035 #ifdef _WIN32
00036   static const char pattern[] = "\\..\\";
00037 #else
00038   static const char pattern[] = "/../";
00039 #endif
00040 
00041 #ifdef _WIN32
00042   static const char file_separator = '\\';
00043   static const char double_file_separator[] = "\\\\";
00044 #else
00045   static const char file_separator = '/';
00046   static const char double_file_separator[] = "//";
00047 #endif
00048 
00049   if (dir.size () == 0) return;
00050 
00051     //
00052     // We first synchronize to using file_separator() in any case.
00053     //
00054 
00055   for (;;)
00056     {
00057       std::string::size_type pos;
00058       pos = dir.find (double_file_separator);
00059       if (pos == std::string::npos) break;
00060       dir.erase (pos, 1);
00061     }
00062 
00063   for (;;)
00064     {
00065       std::string::size_type pos1;
00066       std::string::size_type pos2;
00067 
00068       pos1 = dir.find (pattern);
00069       if (pos1 == std::string::npos) break;
00070 
00071         //
00072         // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
00073         //
00074       std::string p = dir.substr (0, pos1);
00075       
00076         //
00077         // Is "aaaa/xxxx" only made of "xxxx" ?
00078         // 
00079       pos2 = p.find_last_of (file_separator);
00080       
00081       if (pos2 == std::string::npos) break;
00082       
00083         //    01234567890123456
00084         //    aaaa/xxxx/../bbbb
00085         //        2    1   3
00086         //
00087         // erase the "/xxxx/../" pattern
00088         // result will be "aaaa/bbbb"
00089         //
00090       dir.erase (pos2, pos1 + 4 - pos2 - 1);
00091     }
00092 
00093     //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
00094 }
00095 
00096 static void PR_dirname (const std::string& file_name, std::string& result)
00097 {
00098   std::string::size_type pos = file_name.find_last_of ('/');
00099   if (pos == std::string::npos)
00100     {
00101       pos = file_name.find_last_of ('\\');
00102     }
00103 
00104   if (pos == std::string::npos)
00105     {
00106       result = "";
00107     }
00108   else
00109     {
00110       result = file_name;
00111       result.erase (pos);
00112     }
00113 }
00114 
00115 static bool PR_absolute_path (const std::string& name)
00116 {
00117   if (name.size () == 0) return (false);
00118 
00119   if ((name[0] == '/') ||
00120       (name[0] == '\\')) return (true);
00121 
00122   if (name.size () >= 2)
00123     {
00124       if (name[1] == ':')
00125         {
00126           return (true);
00127         }
00128     }
00129   return (false);
00130 }
00131 
00132 static void PR_basename (const std::string& file_name, std::string& result)
00133 {
00134   std::string::size_type pos = file_name.find_last_of ('/');
00135 
00136   if (pos == std::string::npos)
00137     {
00138       pos = file_name.find_last_of ('\\');
00139     }
00140 
00141   if (pos == std::string::npos)
00142     {
00143       result = file_name;
00144     }
00145   else
00146     {
00147       result = file_name.substr (pos + 1);
00148     }
00149 }
00150 
00151 static bool PR_test_exist (const std::string& name, std::string& real_name, PR_file_type file_type)
00152 {
00153   struct stat file_stat;
00154   int status;
00155 
00156   char buf[1024];
00157   strcpy (buf, name.c_str ());
00158 
00159 #ifdef _WIN32
00160   static const char file_separator = '\\';
00161 #else
00162   static const char file_separator = '/';
00163 #endif
00164 
00165   real_name = name;
00166 #ifndef _WIN32
00167   for (;;) {
00168     status = lstat (buf, &file_stat);
00169     if (status == 0) {
00170           if (S_ISLNK (file_stat.st_mode) != 0) {
00171             //std::cout << "#1 " << buf << " stat=" << std::oct << file_stat.st_mode << std::dec << std::endl;
00172             int n = readlink (buf, buf, sizeof (buf));
00173             if (n >= 0) buf[n] = 0;
00174             //std::cout << "test_exist> buf=" << buf << std::endl;
00175             if (PR_absolute_path (buf)) { 
00176           real_name = buf;
00177         }
00178             else {
00179           PR_dirname (real_name, real_name);
00180           real_name += file_separator;
00181           real_name += buf;
00182           PR_compress_path (real_name);
00183           strcpy (buf, real_name.c_str ());
00184         }
00185             //std::cout << "#2 " << real_name << std::endl;
00186             //break;
00187       }
00188       else { 
00189         break;
00190       }
00191     }
00192     else {
00193       break;
00194     }
00195   }
00196 #endif
00197   status = stat (name.c_str (), &file_stat);
00198 
00199   if (status == 0) {
00200     if ((file_stat.st_mode & S_IFDIR) == 0) {
00201       return (file_type == PR_regular_file);
00202     }
00203     else {
00204       return (file_type == PR_directory);
00205     }
00206   }
00207   else {
00208     return (false);
00209   }
00210 }
00211 
00212 static void PR_scan_dir (const std::string& dir_name,
00213                          std::vector<std::string>& list)
00214 {
00215 #ifdef _WIN32
00216   static const char file_separator = '\\';
00217 #else
00218   static const char file_separator = '/';
00219 #endif
00220 
00221   static std::string dir_prefix;
00222   static std::string name_prefix;
00223   static std::string real_name;
00224 
00225   dir_prefix = dir_name;
00226   if (dir_name == "") dir_prefix = ".";
00227 
00228   //std::cout << "PR_scan_dir1> dir_name=" << dir_name << " dir_prefix=" << dir_prefix << std::endl;
00229 
00230   if (!PR_test_exist (dir_prefix, real_name, PR_directory)) {
00231     PR_dirname (dir_prefix, dir_prefix);
00232     PR_basename (dir_name, name_prefix);
00233   }
00234 
00235   bool need_filter = false;
00236 
00237   std::string::size_type wild_card;
00238 
00239   wild_card = name_prefix.find ('*');
00240   if (wild_card != std::string::npos) {
00241     name_prefix.erase (wild_card);
00242 
00243     if (name_prefix.size () > 0) {
00244       need_filter = true;
00245     }
00246   }
00247 
00248   list.clear();
00249 
00250 #ifdef _WIN32
00251 
00252   long dir;
00253   struct _finddata_t entry;
00254 
00255   static std::string search;
00256 
00257   search = dir_prefix;
00258   search += file_separator;
00259   search += "*";
00260 
00261   dir = _findfirst (search.c_str (), &entry);
00262   if (dir > 0) {
00263     for (;;)   {
00264       if ((strcmp ((char*) entry.name, ".") != 0) &&
00265           (strcmp ((char*) entry.name, "..") != 0) &&
00266           (strncmp ((char*) entry.name, ".nfs", 4) != 0)) {
00267         const char* name = entry.name;
00268 
00269         if (need_filter && 
00270           (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0)) continue;
00271         std::string name_entry;
00272         name_entry = dir_prefix;
00273         name_entry += file_separator;
00274         name_entry += name;
00275 
00276         list.push_back (name_entry);
00277       }
00278 
00279       int status = _findnext (dir, &entry);
00280       if (status != 0) {
00281         break;
00282       }
00283     }
00284     _findclose (dir);
00285   }
00286 #else
00287 
00288   DIR* dir = opendir (dir_prefix.c_str ());
00289 
00290   struct dirent* entry;
00291 
00292   if (dir != 0) {
00293     while ((entry = readdir (dir)) != 0) {
00294       //if (entry->d_name[0] == '.') continue;
00295       if (!strcmp ((char*) entry->d_name, ".")) continue;
00296       if (!strcmp ((char*) entry->d_name, "..")) continue;
00297       if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
00298 
00299       const char* name = entry->d_name;
00300 
00301       //std::cout << "scan_dir4> name=" << name << std::endl;
00302 
00303       if (need_filter &&
00304           (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
00305 
00306       std::string name_entry;
00307 
00308       name_entry = dir_prefix;
00309       name_entry += file_separator;
00310       name_entry += name;
00311 
00312       list.push_back (name_entry);
00313     }
00314     closedir (dir);
00315   }
00316 #endif
00317 }
00318 
00319 
00320 static bool PR_find (const std::string& search_base, 
00321                      const std::string& logical_file_prefix, 
00322                      const std::string& logical_file_name, 
00323                      PR_file_type file_type,
00324                      PathResolver::SearchType search_type,
00325                      std::string& result)
00326 {
00327   static int level = 0;
00328 
00329 #ifdef _WIN32
00330   static const char file_separator = '\\';
00331 #else
00332   static const char file_separator = '/';
00333 #endif
00334 
00335   std::string file_path = "";
00336   std::string real_name = "";
00337 
00338   bool found = false;
00339 
00340   //PR_indent (level); std::cout << "PR_find> sb=" << search_base << " lfp=" << logical_file_prefix << " lfn=" << logical_file_name << std::endl;
00341 
00342   if (search_base != "")
00343     {
00344       file_path = search_base;
00345       file_path += file_separator;
00346     }
00347   else
00348     {
00349       file_path = "";
00350     }
00351 
00352   file_path += logical_file_name;
00353 
00354   //PR_indent (level); std::cout << "PR_find> test1 file_path=" << file_path << std::endl;
00355 
00356   result = file_path;
00357   if (PR_test_exist (file_path, result, file_type))
00358     {
00359       found = true;
00360     }
00361 
00362   if (!found && (logical_file_prefix != ""))
00363     {
00364       if (search_base != "")
00365         {
00366           file_path = search_base;
00367           file_path += file_separator;
00368         }
00369       else
00370         {
00371           file_path = "";
00372         }
00373 
00374       file_path += logical_file_prefix;
00375       file_path += file_separator;
00376       file_path += logical_file_name;
00377 
00378       //PR_indent (level); std::cout << "PR_find> test2 file_path=" << file_path << std::endl;
00379 
00380       result = file_path;
00381       if (PR_test_exist (file_path, result, file_type))
00382         {
00383           found = true;
00384         }
00385     }
00386 
00387   //PR_indent (level); std::cout << "PR_find> test3 found=" << found << " search_type=" << search_type << std::endl;
00388 
00389   if (!found && (search_type == PathResolver::RecursiveSearch))
00390     {
00391       std::string dir_name = "";
00392       std::string file_name = "";
00393       std::vector<std::string> list;
00394 
00395       PR_scan_dir (search_base, list);
00396 
00397       std::vector<std::string>::iterator it;
00398 
00399       for (it = list.begin (); it != list.end (); ++it)
00400         {
00401           const std::string& d = *it;
00402 
00403           if (PR_test_exist (d, file_path, PR_directory))
00404             {
00405               //PR_indent (level); std::cout << "d=" << d << std::endl;
00406 
00407               level++;
00408               bool s = PR_find (d, logical_file_prefix, logical_file_name, file_type, search_type, result);
00409               level--;
00410 
00411               if (s)
00412                 {
00413                   //PR_indent (level); std::cout << "PR_find> result=" << result << std::endl;
00414                   found = true;
00415                   break;
00416                 }
00417             }
00418         }
00419     }
00420 
00421   return (found);
00422 }
00423 
00424 static bool PR_find_from_list (const std::string& logical_file_name,
00425                                const std::string& search_list,
00426                                PR_file_type file_type,
00427                                PathResolver::SearchType search_type,
00428                                std::string& result)
00429 {
00430 #ifdef _WIN32
00431   static const char path_separator = ';';
00432 #else
00433   static const char path_separator = ':';
00434 #endif
00435 
00436   std::string::size_type pos = 0;
00437 
00438   std::string file_name = "";
00439   std::string file_prefix = "";
00440 
00441   PR_basename (logical_file_name, file_name);
00442   PR_dirname (logical_file_name, file_prefix);
00443 
00444   std::string real_name = "";
00445 
00446   bool found = false;
00447 
00448   if (PR_find ("", file_prefix, file_name, file_type, search_type, result))
00449     {
00450       found = true;
00451     }
00452 
00453   if (!found)
00454     {
00455       for (int i = 0;;i++)
00456         {
00457           bool ending = false;
00458 
00459           std::string::size_type next = search_list.find (path_separator, pos);
00460 
00461           std::string path = search_list.substr (pos, next - pos);
00462 
00463           if (next == std::string::npos)
00464             {
00465               path = search_list.substr (pos);
00466               ending = true;
00467             }
00468           else
00469             {
00470               path = search_list.substr (pos, next - pos);
00471               pos = next + 1;
00472             }
00473           
00474           //std::cout << "path[" << i << "]=" << path << std::endl;
00475           
00476           if (PR_find (path, file_prefix, file_name, file_type, search_type, result))
00477             {
00478               found = true;
00479               break;
00480             }
00481           
00482           if (ending) break;
00483         }
00484     }
00485 
00486   return (found);
00487 }
00488 
00489 std::string PathResolver::find_file (const std::string& logical_file_name,
00490                                      const std::string& search_path,
00491                                      SearchType search_type)
00492 {
00493   const char* path_env = ::getenv (search_path.c_str ());
00494 
00495   std::string path_list;
00496 
00497   if (path_env != 0)
00498     {
00499       path_list = path_env;
00500     }
00501 
00502   return (find_file_from_list (logical_file_name, path_list, search_type));
00503 }
00504 
00505 std::string PathResolver::find_file_from_list (const std::string& logical_file_name,
00506                                                const std::string& search_list,
00507                                                SearchType search_type)
00508 {
00509   std::string result;
00510 
00511   if (!PR_find_from_list (logical_file_name, search_list, PR_regular_file, search_type, result))
00512     {
00513       result = "";
00514     }
00515 
00516   return (result);
00517 }
00518 
00519 std::string PathResolver::find_directory (const std::string& logical_file_name,
00520                                           const std::string& search_path,
00521                                           SearchType search_type)
00522 {
00523   const char* path_env = ::getenv (search_path.c_str ());
00524 
00525   std::string path_list;
00526 
00527   if (path_env != 0)
00528     {
00529       path_list = path_env;
00530     }
00531 
00532   return (find_directory_from_list (logical_file_name, path_list, search_type));
00533 }
00534 
00535 std::string PathResolver::find_directory_from_list (const std::string& logical_file_name,
00536                                                     const std::string& search_list,
00537                                                     SearchType search_type)
00538 {
00539   std::string result;
00540 
00541   if (!PR_find_from_list (logical_file_name, search_list, PR_directory, search_type, result))
00542     {
00543       result = "";
00544     }
00545 
00546   return (result);
00547 }
00548 
00549 PathResolver::SearchPathStatus PathResolver::check_search_path (const std::string& search_path)
00550 {
00551   const char* path_env = ::getenv (search_path.c_str ());
00552 
00553   if (path_env == 0) return (EnvironmentVariableUndefined);
00554 
00555 #ifdef _WIN32
00556   static const char path_separator = ';';
00557 #else
00558   static const char path_separator = ':';
00559 #endif
00560 
00561   std::string path_list (path_env);
00562 
00563   std::string::size_type pos = 0;
00564 
00565   for (int i = 0;;i++)
00566     {
00567       bool ending = false;
00568 
00569       std::string::size_type next = path_list.find (path_separator, pos);
00570 
00571       std::string path = path_list.substr (pos, next - pos);
00572 
00573       if (next == std::string::npos)
00574         {
00575           path = path_list.substr (pos);
00576           ending = true;
00577         }
00578       else
00579         {
00580           path = path_list.substr (pos, next - pos);
00581           pos = next + 1;
00582         }
00583 
00584       std::string real_name = "";
00585 
00586       if (!PR_test_exist (path, real_name, PR_directory))
00587         {
00588           return (UnknownDirectory);
00589         }
00590 
00591       if (ending) break;
00592     }
00593 
00594   return (Ok);
00595 }
00596 
00597 
00598 PathResolver::SearchPathStatus PathResolverCheckSearchPath (const std::string& search_path)
00599 {
00600   return PathResolver::check_search_path (search_path);
00601 }
00602 
00603 std::string PathResolverFindDirectory (const std::string& logical_file_name,
00604                                         const std::string& search_path)
00605 {
00606   return PathResolver::find_directory (logical_file_name, search_path);
00607 }
00608 
00609 std::string PathResolverFindDirectoryFromList (const std::string& logical_file_name,
00610                                                 const std::string& search_list)
00611 {
00612   return PathResolver::find_directory_from_list (logical_file_name, search_list);
00613 }
00614 
00615 std::string PathResolverFindFile (const std::string& logical_file_name,
00616                                   const std::string& search_path)
00617 {
00618   return PathResolver::find_file (logical_file_name, search_path);
00619 }
00620 
00621 std::string PathResolverFindFileFromList (const std::string& logical_file_name,
00622                                           const std::string& search_list)
00623 {
00624   return PathResolver::find_file_from_list (logical_file_name, search_list);
00625 }
00626 
00627 std::string PathResolverFindXMLFile (const std::string& logical_file_name)
00628 {
00629   return PathResolver::find_file (logical_file_name, "XMLPATH");
00630 }
00631 
00632 std::string PathResolverFindDataFile (const std::string& logical_file_name)
00633 {
00634   return PathResolver::find_file (logical_file_name, "DATAPATH");
00635 }
00636 
00637 }  // System namespace

Generated at Fri Jul 18 11:59:22 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004