| # Gaudi Framework, version v21r7p1 |

Home |  | Generated: 15 Feb 2010

# PathResolver.cpp

Go to the documentation of this file.

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