![]() |
|
|
Generated: 8 Jan 2009 |
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