/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/EventFilter/HltUtilities/HltTools/HltTools-01-00-02/src/PathResolver.cxx

Go to the documentation of this file.
00001 
00002 
00003 #include "HltTools/PathResolver.h"
00004 
00005 #include <cstdlib>
00006 #include <cstdio>
00007 
00008 #include <iostream>
00009 #include <vector>
00010 #include <string.h>
00011 
00012 #include <sys/stat.h>
00013 
00014 #ifdef WIN32
00015 #define stat _stat
00016 #include <direct.h>
00017 #else
00018 #include <unistd.h>
00019 #include <dirent.h>
00020 #endif
00021 
00022 typedef enum
00023   {
00024     PR_regular_file,
00025     PR_directory
00026   } PR_file_type;
00027 
00028 typedef enum
00029   {
00030     PR_local,
00031     PR_recursive
00032   } 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 
00159   strcpy (buf, name.c_str ());
00160 
00161 #ifdef WIN32
00162   static const char file_separator = '\\';
00163 #else
00164   static const char file_separator = '/';
00165 #endif
00166 
00167   real_name = name;
00168 
00169   //std::cout << "test_file> name=" << name << std::endl;
00170 
00171   for (;;)
00172     {
00173       status = lstat (buf, &file_stat);
00174 
00175       if (status == 0)
00176         {
00177           if (S_ISLNK (file_stat.st_mode) != 0)
00178             {
00179               //std::cout << "#1 " << buf << " stat=" << std::oct << file_stat.st_mode << std::dec << std::endl;
00180 
00181               int n = readlink (buf, buf, sizeof (buf));
00182               if (n >= 0) buf[n] = 0;
00183 
00184               //std::cout << "test_exist> buf=" << buf << std::endl;
00185 
00186               if (PR_absolute_path (buf))
00187                 {
00188                   real_name = buf;
00189                 }
00190               else
00191                 {
00192                   PR_dirname (real_name, real_name);
00193                   real_name += file_separator;
00194                   real_name += buf;
00195 
00196                   PR_compress_path (real_name);
00197 
00198                   strcpy (buf, real_name.c_str ());
00199                 }
00200 
00201               //std::cout << "#2 " << real_name << std::endl;
00202 
00203               //break;
00204             }
00205           else
00206             {
00207               break;
00208             }
00209         }
00210       else
00211         {
00212           break;
00213         }
00214     }
00215 
00216   status = stat (name.c_str (), &file_stat);
00217 
00218   if (status == 0)
00219     {
00220       if ((file_stat.st_mode & S_IFDIR) == 0)
00221         {
00222           return (file_type == PR_regular_file);
00223         }
00224       else
00225         {
00226           return (file_type == PR_directory);
00227         }
00228     }
00229   else
00230     {
00231       return (false);
00232     }
00233 }
00234 
00235 static void PR_scan_dir (const std::string& dir_name,
00236                          std::vector<std::string>& list)
00237 {
00238 #ifdef WIN32
00239   static const char file_separator = '\\';
00240 #else
00241   static const char file_separator = '/';
00242 #endif
00243 
00244   static std::string dir_prefix;
00245   static std::string name_prefix;
00246   static std::string real_name;
00247 
00248   dir_prefix = dir_name;
00249   if (dir_name == "") dir_prefix = ".";
00250 
00251   //std::cout << "PR_scan_dir1> dir_name=" << dir_name << " dir_prefix=" << dir_prefix << std::endl;
00252 
00253   if (!PR_test_exist (dir_prefix, real_name, PR_directory))
00254     {
00255       PR_dirname (dir_prefix, dir_prefix);
00256       PR_basename (dir_name, name_prefix);
00257     }
00258 
00259   bool need_filter = false;
00260 
00261   std::string::size_type wild_card;
00262     //unsigned int wild_card;
00263 
00264   wild_card = name_prefix.find ('*');
00265   if (wild_card != std::string::npos)
00266     {
00267       name_prefix.erase (wild_card);
00268 
00269       if (name_prefix.size () > 0)
00270         {
00271           need_filter = true;
00272         }
00273 
00274     }
00275 
00276   list.clear ();
00277 
00278 #ifdef WIN32
00279 
00280   long dir;
00281   struct _finddata_t entry;
00282 
00283   static std::string search;
00284 
00285   search = dir_prefix;
00286   search += file_separator;
00287   search += "*";
00288 
00289   dir = _findfirst (search.c_str (), &entry);
00290   if (dir > 0)
00291     {
00292       for (;;)
00293         {
00294           if ((strcmp ((char*) entry.name, ".") != 0) &&
00295               (strcmp ((char*) entry.name, "..") != 0) &&
00296               (strncmp ((char*) entry.name, ".nfs", 4) != 0))
00297             {
00298               const char* name = entry.name;
00299 
00300               if (!need_filter ||
00301                   (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
00302                 {
00303                   std::string& name_entry = list.add ();
00304 
00305                   name_entry = dir_prefix;
00306                   name_entry += file_separator;
00307                   name_entry += name;
00308                 }
00309             }
00310 
00311           int status = _findnext (dir, &entry);
00312           if (status != 0)
00313             {
00314               break;
00315             }
00316         }
00317 
00318       _findclose (dir);
00319     }
00320 #else
00321 
00322   //std::cout << "scan_dir2> dir_prefix=" << dir_prefix << std::endl;
00323 
00324   DIR* dir = opendir (dir_prefix.c_str ());
00325 
00326   struct dirent* entry;
00327 
00328   if (dir != 0)
00329     {
00330 
00331       //std::cout << "scan_dir3> need_filter=" << need_filter << std::endl;
00332 
00333       while ((entry = readdir (dir)) != 0)
00334         {
00335           //if (entry->d_name[0] == '.') continue;
00336           if (!strcmp ((char*) entry->d_name, ".")) continue;
00337           if (!strcmp ((char*) entry->d_name, "..")) continue;
00338           if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
00339 
00340           const char* name = entry->d_name;
00341 
00342           //std::cout << "scan_dir4> name=" << name << std::endl;
00343 
00344           if (need_filter &&
00345               (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
00346 
00347           std::string name_entry;
00348 
00349           name_entry = dir_prefix;
00350           name_entry += file_separator;
00351           name_entry += name;
00352 
00353           list.push_back (name_entry);
00354         }
00355 
00356       closedir (dir);
00357     }
00358 #endif
00359 
00360 }
00361 
00362 static void PR_indent (int level)
00363 {
00364   while (level > 0)
00365     {
00366       std::cout << "  ";
00367       level --;
00368     }
00369 }
00370 
00371 static bool PR_find (const std::string& search_base, 
00372                      const std::string& logical_file_prefix, 
00373                      const std::string& logical_file_name, 
00374                      PR_file_type file_type,
00375                      PathResolver::SearchType search_type,
00376                      std::string& result)
00377 {
00378   static int level = 0;
00379 
00380 #ifdef WIN32
00381   static const char file_separator = '\\';
00382 #else
00383   static const char file_separator = '/';
00384 #endif
00385 
00386   std::string file_path = "";
00387   std::string real_name = "";
00388 
00389   bool found = false;
00390 
00391   //PR_indent (level); std::cout << "PR_find> sb=" << search_base << " lfp=" << logical_file_prefix << " lfn=" << logical_file_name << std::endl;
00392 
00393   if (search_base != "")
00394     {
00395       file_path = search_base;
00396       file_path += file_separator;
00397     }
00398   else
00399     {
00400       file_path = "";
00401     }
00402 
00403   file_path += logical_file_name;
00404 
00405   //PR_indent (level); std::cout << "PR_find> test1 file_path=" << file_path << std::endl;
00406 
00407   result = file_path;
00408   if (PR_test_exist (file_path, result, file_type))
00409     {
00410       found = true;
00411     }
00412 
00413   if (!found && (logical_file_prefix != ""))
00414     {
00415       if (search_base != "")
00416         {
00417           file_path = search_base;
00418           file_path += file_separator;
00419         }
00420       else
00421         {
00422           file_path = "";
00423         }
00424 
00425       file_path += logical_file_prefix;
00426       file_path += file_separator;
00427       file_path += logical_file_name;
00428 
00429       //PR_indent (level); std::cout << "PR_find> test2 file_path=" << file_path << std::endl;
00430 
00431       result = file_path;
00432       if (PR_test_exist (file_path, result, file_type))
00433         {
00434           found = true;
00435         }
00436     }
00437 
00438   //PR_indent (level); std::cout << "PR_find> test3 found=" << found << " search_type=" << search_type << std::endl;
00439 
00440   if (!found && (search_type == PathResolver::RecursiveSearch))
00441     {
00442       std::string dir_name = "";
00443       std::string file_name = "";
00444       std::vector<std::string> list;
00445 
00446       PR_scan_dir (search_base, list);
00447 
00448       std::vector<std::string>::iterator it;
00449 
00450       for (it = list.begin (); it != list.end (); ++it)
00451         {
00452           const std::string& d = *it;
00453 
00454           if (PR_test_exist (d, file_path, PR_directory))
00455             {
00456               //PR_indent (level); std::cout << "d=" << d << std::endl;
00457 
00458               level++;
00459               bool s = PR_find (d, logical_file_prefix, logical_file_name, file_type, search_type, result);
00460               level--;
00461 
00462               if (s)
00463                 {
00464                   //PR_indent (level); std::cout << "PR_find> result=" << result << std::endl;
00465                   found = true;
00466                   break;
00467                 }
00468             }
00469         }
00470     }
00471 
00472   return (found);
00473 }
00474 
00475 static bool PR_find_from_list (const std::string& logical_file_name,
00476                                const std::string& search_list,
00477                                PR_file_type file_type,
00478                                PathResolver::SearchType search_type,
00479                                std::string& result)
00480 {
00481 #ifdef WIN32
00482   static const char path_separator = ';';
00483 #else
00484   static const char path_separator = ':';
00485 #endif
00486 
00487   std::string::size_type pos = 0;
00488 
00489   std::string file_name = "";
00490   std::string file_prefix = "";
00491 
00492   PR_basename (logical_file_name, file_name);
00493   PR_dirname (logical_file_name, file_prefix);
00494 
00495   std::string real_name = "";
00496 
00497   bool found = false;
00498 
00499   if (PR_find ("", file_prefix, file_name, file_type, search_type, result))
00500     {
00501       found = true;
00502     }
00503 
00504   if (!found)
00505     {
00506       for (int i = 0;;i++)
00507         {
00508           bool ending = false;
00509 
00510           std::string::size_type next = search_list.find (path_separator, pos);
00511 
00512           std::string path = search_list.substr (pos, next - pos);
00513 
00514           if (next == std::string::npos)
00515             {
00516               path = search_list.substr (pos);
00517               ending = true;
00518             }
00519           else
00520             {
00521               path = search_list.substr (pos, next - pos);
00522               pos = next + 1;
00523             }
00524           
00525           //std::cout << "path[" << i << "]=" << path << std::endl;
00526           
00527           if (PR_find (path, file_prefix, file_name, file_type, search_type, result))
00528             {
00529               found = true;
00530               break;
00531             }
00532           
00533           if (ending) break;
00534         }
00535     }
00536 
00537   return (found);
00538 }
00539 
00540 std::string PathResolver::find_file (const std::string& logical_file_name,
00541                                      const std::string& search_path,
00542                                      SearchType search_type)
00543 {
00544   const char* path_env = ::getenv (search_path.c_str ());
00545 
00546   std::string path_list;
00547 
00548   if (path_env != 0)
00549     {
00550       path_list = path_env;
00551     }
00552 
00553   return (find_file_from_list (logical_file_name, path_list, search_type));
00554 }
00555 
00556 std::string PathResolver::find_file_from_list (const std::string& logical_file_name,
00557                                                const std::string& search_list,
00558                                                SearchType search_type)
00559 {
00560   std::string result;
00561 
00562   if (!PR_find_from_list (logical_file_name, search_list, PR_regular_file, search_type, result))
00563     {
00564       result = "";
00565     }
00566 
00567   return (result);
00568 }
00569 
00570 std::string PathResolver::find_directory (const std::string& logical_file_name,
00571                                           const std::string& search_path,
00572                                           SearchType search_type)
00573 {
00574   const char* path_env = ::getenv (search_path.c_str ());
00575 
00576   std::string path_list;
00577 
00578   if (path_env != 0)
00579     {
00580       path_list = path_env;
00581     }
00582 
00583   return (find_directory_from_list (logical_file_name, path_list, search_type));
00584 }
00585 
00586 std::string PathResolver::find_directory_from_list (const std::string& logical_file_name,
00587                                                     const std::string& search_list,
00588                                                     SearchType search_type)
00589 {
00590   std::string result;
00591 
00592   if (!PR_find_from_list (logical_file_name, search_list, PR_directory, search_type, result))
00593     {
00594       result = "";
00595     }
00596 
00597   return (result);
00598 }
00599 
00600 PathResolver::SearchPathStatus PathResolver::check_search_path (const std::string& search_path)
00601 {
00602   const char* path_env = ::getenv (search_path.c_str ());
00603 
00604   if (path_env == 0) return (EnvironmentVariableUndefined);
00605 
00606 #ifdef WIN32
00607   static const char path_separator = ';';
00608 #else
00609   static const char path_separator = ':';
00610 #endif
00611 
00612   std::string path_list (path_env);
00613 
00614   std::string::size_type pos = 0;
00615 
00616   for (int i = 0;;i++)
00617     {
00618       bool ending = false;
00619 
00620       std::string::size_type next = path_list.find (path_separator, pos);
00621 
00622       std::string path = path_list.substr (pos, next - pos);
00623 
00624       if (next == std::string::npos)
00625         {
00626           path = path_list.substr (pos);
00627           ending = true;
00628         }
00629       else
00630         {
00631           path = path_list.substr (pos, next - pos);
00632           pos = next + 1;
00633         }
00634 
00635       std::string real_name = "";
00636 
00637       if (!PR_test_exist (path, real_name, PR_directory))
00638         {
00639           return (UnknownDirectory);
00640         }
00641 
00642       if (ending) break;
00643     }
00644 
00645   return (Ok);
00646 }
00647 
00648 
00649 
00650 
00651 extern "C"
00652 {
00653   PathResolver::SearchPathStatus PathResolverCheckSearchPath (const std::string& search_path)
00654   {
00655     return PathResolver::check_search_path (search_path);
00656   }
00657   
00658   std::string PathResolverFindDirectory (const std::string& logical_file_name,
00659                                          const std::string& search_path)
00660   {
00661     return PathResolver::find_directory (logical_file_name, search_path);
00662   }
00663   
00664   std::string PathResolverFindDirectoryFromList (const std::string& logical_file_name,
00665                                                  const std::string& search_list)
00666   {
00667     return PathResolver::find_directory_from_list (logical_file_name, search_list);
00668   }
00669   
00670   std::string PathResolverFindFile (const std::string& logical_file_name,
00671                                     const std::string& search_path)
00672   {
00673     return PathResolver::find_file (logical_file_name, search_path);
00674   }
00675   
00676   std::string PathResolverFindFileFromList (const std::string& logical_file_name,
00677                                             const std::string& search_list)
00678   {
00679     return PathResolver::find_file_from_list (logical_file_name, search_list);
00680   }
00681   
00682   std::string PathResolverFindXMLFile (const std::string& logical_file_name)
00683   {
00684     return PathResolver::find_file (logical_file_name, "XMLPATH");
00685   }
00686   
00687   std::string PathResolverFindDataFile (const std::string& logical_file_name)
00688   {
00689     return PathResolver::find_file (logical_file_name, "DATAPATH");
00690   }
00691 }

Generated on Tue Nov 29 23:12:07 2016 for BOSS_7.0.2 by  doxygen 1.4.7