| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# 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   bool found = false;
    00340
    00341   //PR_indent (level); std::cout << "PR_find> sb=" << search_base << " lfp=" << logical_file_prefix << " lfn=" << logical_file_name << std::endl;
    00342
    00343   if (search_base != "")
    00344     {
    00345       file_path = search_base;
    00346       file_path += file_separator;
    00347     }
    00348   else
    00349     {
    00350       file_path = "";
    00351     }
    00352
    00353   file_path += logical_file_name;
    00354
    00355   //PR_indent (level); std::cout << "PR_find> test1 file_path=" << file_path << std::endl;
    00356
    00357   result = file_path;
    00358   if (PR_test_exist (file_path, result, file_type))
    00359     {
    00360       found = true;
    00361     }
    00362
    00363   if (!found && (logical_file_prefix != ""))
    00364     {
    00365       if (search_base != "")
    00366         {
    00367           file_path = search_base;
    00368           file_path += file_separator;
    00369         }
    00370       else
    00371         {
    00372           file_path = "";
    00373         }
    00374
    00375       file_path += logical_file_prefix;
    00376       file_path += file_separator;
    00377       file_path += logical_file_name;
    00378
    00379       //PR_indent (level); std::cout << "PR_find> test2 file_path=" << file_path << std::endl;
    00380
    00381       result = file_path;
    00382       if (PR_test_exist (file_path, result, file_type))
    00383         {
    00384           found = true;
    00385         }
    00386     }
    00387
    00388   //PR_indent (level); std::cout << "PR_find> test3 found=" << found << " search_type=" << search_type << std::endl;
    00389
    00390   if (!found && (search_type == PathResolver::RecursiveSearch))
    00391     {
    00392       std::string dir_name = "";
    00393       std::string file_name = "";
    00394       std::vector<std::string> list;
    00395
    00396       PR_scan_dir (search_base, list);
    00397
    00398       std::vector<std::string>::iterator it;
    00399
    00400       for (it = list.begin (); it != list.end (); ++it)
    00401         {
    00402           const std::string& d = *it;
    00403
    00404           if (PR_test_exist (d, file_path, PR_directory))
    00405             {
    00406               //PR_indent (level); std::cout << "d=" << d << std::endl;
    00407
    00408               level++;
    00409               bool s = PR_find (d, logical_file_prefix, logical_file_name, file_type, search_type, result);
    00410               level--;
    00411
    00412               if (s)
    00413                 {
    00414                   //PR_indent (level); std::cout << "PR_find> result=" << result << std::endl;
    00415                   found = true;
    00416                   break;
    00417                 }
    00418             }
    00419         }
    00420     }
    00421
    00422   return (found);
    00423 }
    00424
    00425 static bool PR_find_from_list (const std::string& logical_file_name,
    00426                                const std::string& search_list,
    00427                                PR_file_type file_type,
    00428                                PathResolver::SearchType search_type,
    00429                                std::string& result)
    00430 {
    00431 #ifdef _WIN32
    00432   static const char path_separator = ';';
    00433 #else
    00434   static const char path_separator = ':';
    00435 #endif
    00436
    00437   std::string::size_type pos = 0;
    00438
    00439   std::string file_name = "";
    00440   std::string file_prefix = "";
    00441
    00442   PR_basename (logical_file_name, file_name);
    00443   PR_dirname (logical_file_name, file_prefix);
    00444
    00445   std::string real_name = "";
    00446
    00447   bool found = false;
    00448
    00449   if (PR_find ("", file_prefix, file_name, file_type, search_type, result))
    00450     {
    00451       found = true;
    00452     }
    00453
    00454   if (!found)
    00455     {
    00456       for (int i = 0;;i++)
    00457         {
    00458           bool ending = false;
    00459
    00460           std::string::size_type next = search_list.find (path_separator, pos);
    00461
    00462           std::string path = search_list.substr (pos, next - pos);
    00463
    00464           if (next == std::string::npos)
    00465             {
    00466               path = search_list.substr (pos);
    00467               ending = true;
    00468             }
    00469           else
    00470             {
    00471               path = search_list.substr (pos, next - pos);
    00472               pos = next + 1;
    00473             }
    00474
    00475           //std::cout << "path[" << i << "]=" << path << std::endl;
    00476
    00477           if (PR_find (path, file_prefix, file_name, file_type, search_type, result))
    00478             {
    00479               found = true;
    00480               break;
    00481             }
    00482
    00483           if (ending) break;
    00484         }
    00485     }
    00486
    00487   return (found);
    00488 }
    00489
    00490 std::string PathResolver::find_file (const std::string& logical_file_name,
    00491                                      const std::string& search_path,
    00492                                      SearchType search_type)
    00493 {
    00494   const char* path_env = ::getenv (search_path.c_str ());
    00495
    00496   std::string path_list;
    00497
    00498   if (path_env != 0)
    00499     {
    00500       path_list = path_env;
    00501     }
    00502
    00503   return (find_file_from_list (logical_file_name, path_list, search_type));
    00504 }
    00505
    00506 std::string PathResolver::find_file_from_list (const std::string& logical_file_name,
    00507                                                const std::string& search_list,
    00508                                                SearchType search_type)
    00509 {
    00510   std::string result;
    00511
    00512   if (!PR_find_from_list (logical_file_name, search_list, PR_regular_file, search_type, result))
    00513     {
    00514       result = "";
    00515     }
    00516
    00517   return (result);
    00518 }
    00519
    00520 std::string PathResolver::find_directory (const std::string& logical_file_name,
    00521                                           const std::string& search_path,
    00522                                           SearchType search_type)
    00523 {
    00524   const char* path_env = ::getenv (search_path.c_str ());
    00525
    00526   std::string path_list;
    00527
    00528   if (path_env != 0)
    00529     {
    00530       path_list = path_env;
    00531     }
    00532
    00533   return (find_directory_from_list (logical_file_name, path_list, search_type));
    00534 }
    00535
    00536 std::string PathResolver::find_directory_from_list (const std::string& logical_file_name,
    00537                                                     const std::string& search_list,
    00538                                                     SearchType search_type)
    00539 {
    00540   std::string result;
    00541
    00542   if (!PR_find_from_list (logical_file_name, search_list, PR_directory, search_type, result))
    00543     {
    00544       result = "";
    00545     }
    00546
    00547   return (result);
    00548 }
    00549
    00550 PathResolver::SearchPathStatus PathResolver::check_search_path (const std::string& search_path)
    00551 {
    00552   const char* path_env = ::getenv (search_path.c_str ());
    00553
    00554   if (path_env == 0) return (EnvironmentVariableUndefined);
    00555
    00556 #ifdef _WIN32
    00557   static const char path_separator = ';';
    00558 #else
    00559   static const char path_separator = ':';
    00560 #endif
    00561
    00562   std::string path_list (path_env);
    00563
    00564   std::string::size_type pos = 0;
    00565
    00566   for (int i = 0;;i++)
    00567     {
    00568       bool ending = false;
    00569
    00570       std::string::size_type next = path_list.find (path_separator, pos);
    00571
    00572       std::string path = path_list.substr (pos, next - pos);
    00573
    00574       if (next == std::string::npos)
    00575         {
    00576           path = path_list.substr (pos);
    00577           ending = true;
    00578         }
    00579       else
    00580         {
    00581           path = path_list.substr (pos, next - pos);
    00582           pos = next + 1;
    00583         }
    00584
    00585       std::string real_name = "";
    00586
    00587       if (!PR_test_exist (path, real_name, PR_directory))
    00588         {
    00589           return (UnknownDirectory);
    00590         }
    00591
    00592       if (ending) break;
    00593     }
    00594
    00595   return (Ok);
    00596 }
    00597
    00598
    00599 PathResolver::SearchPathStatus PathResolverCheckSearchPath (const std::string& search_path)
    00600 {
    00601   return PathResolver::check_search_path (search_path);
    00602 }
    00603
    00604 std::string PathResolverFindDirectory (const std::string& logical_file_name,
    00605                                         const std::string& search_path)
    00606 {
    00607   return PathResolver::find_directory (logical_file_name, search_path);
    00608 }
    00609
    00610 std::string PathResolverFindDirectoryFromList (const std::string& logical_file_name,
    00611                                                 const std::string& search_list)
    00612 {
    00613   return PathResolver::find_directory_from_list (logical_file_name, search_list);
    00614 }
    00615
    00616 std::string PathResolverFindFile (const std::string& logical_file_name,
    00617                                   const std::string& search_path)
    00618 {
    00619   return PathResolver::find_file (logical_file_name, search_path);
    00620 }
    00621
    00622 std::string PathResolverFindFileFromList (const std::string& logical_file_name,
    00623                                           const std::string& search_list)
    00624 {
    00625   return PathResolver::find_file_from_list (logical_file_name, search_list);
    00626 }
    00627
    00628 std::string PathResolverFindXMLFile (const std::string& logical_file_name)
    00629 {
    00630   return PathResolver::find_file (logical_file_name, "XMLPATH");
    00631 }
    00632
    00633 std::string PathResolverFindDataFile (const std::string& logical_file_name)
    00634 {
    00635   return PathResolver::find_file (logical_file_name, "DATAPATH");
    00636 }
    00637
    00638 }  // System namespace