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

Generated at Thu Jan 8 17:44:21 2009 for Gaudi Framework, version v20r4 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004