| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# 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