Gaudi Framework, version v21r8

Home   Generated: 17 Mar 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

Generated at Wed Mar 17 18:06:35 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004