CGEM BOSS 6.6.5.i
BESIII Offline Software System
Loading...
Searching...
No Matches
PathResolver.cxx
Go to the documentation of this file.
1
2
4
5#include <cstdlib>
6#include <cstdio>
7
8#include <iostream>
9#include <vector>
10#include <string.h>
11
12#include <sys/stat.h>
13
14#ifdef WIN32
15#define stat _stat
16#include <direct.h>
17#else
18#include <unistd.h>
19#include <dirent.h>
20#endif
21
27
33
34static void PR_compress_path (std::string& dir)
35{
36#ifdef WIN32
37 static const char pattern[] = "\\..\\";
38#else
39 static const char pattern[] = "/../";
40#endif
41
42#ifdef WIN32
43 static const char file_separator = '\\';
44 static const char double_file_separator[] = "\\\\";
45#else
46 static const char file_separator = '/';
47 static const char double_file_separator[] = "//";
48#endif
49
50 if (dir.size () == 0) return;
51
52 //
53 // We first synchronize to using file_separator() in any case.
54 //
55
56 for (;;)
57 {
58 std::string::size_type pos;
59 pos = dir.find (double_file_separator);
60 if (pos == std::string::npos) break;
61 dir.erase (pos, 1);
62 }
63
64 for (;;)
65 {
66 std::string::size_type pos1;
67 std::string::size_type pos2;
68
69 pos1 = dir.find (pattern);
70 if (pos1 == std::string::npos) break;
71
72 //
73 // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
74 //
75 std::string p = dir.substr (0, pos1);
76
77 //
78 // Is "aaaa/xxxx" only made of "xxxx" ?
79 //
80 pos2 = p.find_last_of (file_separator);
81
82 if (pos2 == std::string::npos) break;
83
84 // 01234567890123456
85 // aaaa/xxxx/../bbbb
86 // 2 1 3
87 //
88 // erase the "/xxxx/../" pattern
89 // result will be "aaaa/bbbb"
90 //
91 dir.erase (pos2, pos1 + 4 - pos2 - 1);
92 }
93
94 //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
95}
96
97static void PR_dirname (const std::string& file_name, std::string& result)
98{
99 std::string::size_type pos = file_name.find_last_of ('/');
100 if (pos == std::string::npos)
101 {
102 pos = file_name.find_last_of ('\\');
103 }
104
105 if (pos == std::string::npos)
106 {
107 result = "";
108 }
109 else
110 {
111 result = file_name;
112 result.erase (pos);
113 }
114}
115
116static bool PR_absolute_path (const std::string& name)
117{
118 if (name.size () == 0) return (false);
119
120 if ((name[0] == '/') ||
121 (name[0] == '\\')) return (true);
122
123 if (name.size () >= 2)
124 {
125 if (name[1] == ':')
126 {
127 return (true);
128 }
129 }
130 return (false);
131}
132
133static void PR_basename (const std::string& file_name, std::string& result)
134{
135 std::string::size_type pos = file_name.find_last_of ('/');
136
137 if (pos == std::string::npos)
138 {
139 pos = file_name.find_last_of ('\\');
140 }
141
142 if (pos == std::string::npos)
143 {
144 result = file_name;
145 }
146 else
147 {
148 result = file_name.substr (pos + 1);
149 }
150}
151
152static bool PR_test_exist (const std::string& name, std::string& real_name, PR_file_type file_type)
153{
154 struct stat file_stat;
155 int status;
156
157 char buf[1024];
158
159 strcpy (buf, name.c_str ());
160
161#ifdef WIN32
162 static const char file_separator = '\\';
163#else
164 static const char file_separator = '/';
165#endif
166
167 real_name = name;
168
169 //std::cout << "test_file> name=" << name << std::endl;
170
171 for (;;)
172 {
173 status = lstat (buf, &file_stat);
174
175 if (status == 0)
176 {
177 if (S_ISLNK (file_stat.st_mode) != 0)
178 {
179 //std::cout << "#1 " << buf << " stat=" << std::oct << file_stat.st_mode << std::dec << std::endl;
180
181 int n = readlink (buf, buf, sizeof (buf));
182 if (n >= 0) buf[n] = 0;
183
184 //std::cout << "test_exist> buf=" << buf << std::endl;
185
186 if (PR_absolute_path (buf))
187 {
188 real_name = buf;
189 }
190 else
191 {
192 PR_dirname (real_name, real_name);
193 real_name += file_separator;
194 real_name += buf;
195
196 PR_compress_path (real_name);
197
198 strcpy (buf, real_name.c_str ());
199 }
200
201 //std::cout << "#2 " << real_name << std::endl;
202
203 //break;
204 }
205 else
206 {
207 break;
208 }
209 }
210 else
211 {
212 break;
213 }
214 }
215
216 status = stat (name.c_str (), &file_stat);
217
218 if (status == 0)
219 {
220 if ((file_stat.st_mode & S_IFDIR) == 0)
221 {
222 return (file_type == PR_regular_file);
223 }
224 else
225 {
226 return (file_type == PR_directory);
227 }
228 }
229 else
230 {
231 return (false);
232 }
233}
234
235static void PR_scan_dir (const std::string& dir_name,
236 std::vector<std::string>& list)
237{
238#ifdef WIN32
239 static const char file_separator = '\\';
240#else
241 static const char file_separator = '/';
242#endif
243
244 static std::string dir_prefix;
245 static std::string name_prefix;
246 static std::string real_name;
247
248 dir_prefix = dir_name;
249 if (dir_name == "") dir_prefix = ".";
250
251 //std::cout << "PR_scan_dir1> dir_name=" << dir_name << " dir_prefix=" << dir_prefix << std::endl;
252
253 if (!PR_test_exist (dir_prefix, real_name, PR_directory))
254 {
255 PR_dirname (dir_prefix, dir_prefix);
256 PR_basename (dir_name, name_prefix);
257 }
258
259 bool need_filter = false;
260
261 std::string::size_type wild_card;
262 //unsigned int wild_card;
263
264 wild_card = name_prefix.find ('*');
265 if (wild_card != std::string::npos)
266 {
267 name_prefix.erase (wild_card);
268
269 if (name_prefix.size () > 0)
270 {
271 need_filter = true;
272 }
273
274 }
275
276 list.clear ();
277
278#ifdef WIN32
279
280 long dir;
281 struct _finddata_t entry;
282
283 static std::string search;
284
285 search = dir_prefix;
286 search += file_separator;
287 search += "*";
288
289 dir = _findfirst (search.c_str (), &entry);
290 if (dir > 0)
291 {
292 for (;;)
293 {
294 if ((strcmp ((char*) entry.name, ".") != 0) &&
295 (strcmp ((char*) entry.name, "..") != 0) &&
296 (strncmp ((char*) entry.name, ".nfs", 4) != 0))
297 {
298 const char* name = entry.name;
299
300 if (!need_filter ||
301 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
302 {
303 std::string& name_entry = list.add ();
304
305 name_entry = dir_prefix;
306 name_entry += file_separator;
307 name_entry += name;
308 }
309 }
310
311 int status = _findnext (dir, &entry);
312 if (status != 0)
313 {
314 break;
315 }
316 }
317
318 _findclose (dir);
319 }
320#else
321
322 //std::cout << "scan_dir2> dir_prefix=" << dir_prefix << std::endl;
323
324 DIR* dir = opendir (dir_prefix.c_str ());
325
326 struct dirent* entry;
327
328 if (dir != 0)
329 {
330
331 //std::cout << "scan_dir3> need_filter=" << need_filter << std::endl;
332
333 while ((entry = readdir (dir)) != 0)
334 {
335 //if (entry->d_name[0] == '.') continue;
336 if (!strcmp ((char*) entry->d_name, ".")) continue;
337 if (!strcmp ((char*) entry->d_name, "..")) continue;
338 if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
339
340 const char* name = entry->d_name;
341
342 //std::cout << "scan_dir4> name=" << name << std::endl;
343
344 if (need_filter &&
345 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
346
347 std::string name_entry;
348
349 name_entry = dir_prefix;
350 name_entry += file_separator;
351 name_entry += name;
352
353 list.push_back (name_entry);
354 }
355
356 closedir (dir);
357 }
358#endif
359
360}
361
362static void PR_indent (int level)
363{
364 while (level > 0)
365 {
366 std::cout << " ";
367 level --;
368 }
369}
370
371static bool PR_find (const std::string& search_base,
372 const std::string& logical_file_prefix,
373 const std::string& logical_file_name,
374 PR_file_type file_type,
375 PathResolver::SearchType search_type,
376 std::string& result)
377{
378 static int level = 0;
379
380#ifdef WIN32
381 static const char file_separator = '\\';
382#else
383 static const char file_separator = '/';
384#endif
385
386 std::string file_path = "";
387 std::string real_name = "";
388
389 bool found = false;
390
391 //PR_indent (level); std::cout << "PR_find> sb=" << search_base << " lfp=" << logical_file_prefix << " lfn=" << logical_file_name << std::endl;
392
393 if (search_base != "")
394 {
395 file_path = search_base;
396 file_path += file_separator;
397 }
398 else
399 {
400 file_path = "";
401 }
402
403 file_path += logical_file_name;
404
405 //PR_indent (level); std::cout << "PR_find> test1 file_path=" << file_path << std::endl;
406
407 result = file_path;
408 if (PR_test_exist (file_path, result, file_type))
409 {
410 found = true;
411 }
412
413 if (!found && (logical_file_prefix != ""))
414 {
415 if (search_base != "")
416 {
417 file_path = search_base;
418 file_path += file_separator;
419 }
420 else
421 {
422 file_path = "";
423 }
424
425 file_path += logical_file_prefix;
426 file_path += file_separator;
427 file_path += logical_file_name;
428
429 //PR_indent (level); std::cout << "PR_find> test2 file_path=" << file_path << std::endl;
430
431 result = file_path;
432 if (PR_test_exist (file_path, result, file_type))
433 {
434 found = true;
435 }
436 }
437
438 //PR_indent (level); std::cout << "PR_find> test3 found=" << found << " search_type=" << search_type << std::endl;
439
440 if (!found && (search_type == PathResolver::RecursiveSearch))
441 {
442 std::string dir_name = "";
443 std::string file_name = "";
444 std::vector<std::string> list;
445
446 PR_scan_dir (search_base, list);
447
448 std::vector<std::string>::iterator it;
449
450 for (it = list.begin (); it != list.end (); ++it)
451 {
452 const std::string& d = *it;
453
454 if (PR_test_exist (d, file_path, PR_directory))
455 {
456 //PR_indent (level); std::cout << "d=" << d << std::endl;
457
458 level++;
459 bool s = PR_find (d, logical_file_prefix, logical_file_name, file_type, search_type, result);
460 level--;
461
462 if (s)
463 {
464 //PR_indent (level); std::cout << "PR_find> result=" << result << std::endl;
465 found = true;
466 break;
467 }
468 }
469 }
470 }
471
472 return (found);
473}
474
475static bool PR_find_from_list (const std::string& logical_file_name,
476 const std::string& search_list,
477 PR_file_type file_type,
478 PathResolver::SearchType search_type,
479 std::string& result)
480{
481#ifdef WIN32
482 static const char path_separator = ';';
483#else
484 static const char path_separator = ':';
485#endif
486
487 std::string::size_type pos = 0;
488
489 std::string file_name = "";
490 std::string file_prefix = "";
491
492 PR_basename (logical_file_name, file_name);
493 PR_dirname (logical_file_name, file_prefix);
494
495 std::string real_name = "";
496
497 bool found = false;
498
499 if (PR_find ("", file_prefix, file_name, file_type, search_type, result))
500 {
501 found = true;
502 }
503
504 if (!found)
505 {
506 for (int i = 0;;i++)
507 {
508 bool ending = false;
509
510 std::string::size_type next = search_list.find (path_separator, pos);
511
512 std::string path = search_list.substr (pos, next - pos);
513
514 if (next == std::string::npos)
515 {
516 path = search_list.substr (pos);
517 ending = true;
518 }
519 else
520 {
521 path = search_list.substr (pos, next - pos);
522 pos = next + 1;
523 }
524
525 //std::cout << "path[" << i << "]=" << path << std::endl;
526
527 if (PR_find (path, file_prefix, file_name, file_type, search_type, result))
528 {
529 found = true;
530 break;
531 }
532
533 if (ending) break;
534 }
535 }
536
537 return (found);
538}
539
540std::string PathResolver::find_file (const std::string& logical_file_name,
541 const std::string& search_path,
542 SearchType search_type)
543{
544 const char* path_env = ::getenv (search_path.c_str ());
545
546 std::string path_list;
547
548 if (path_env != 0)
549 {
550 path_list = path_env;
551 }
552
553 return (find_file_from_list (logical_file_name, path_list, search_type));
554}
555
556std::string PathResolver::find_file_from_list (const std::string& logical_file_name,
557 const std::string& search_list,
558 SearchType search_type)
559{
560 std::string result;
561
562 if (!PR_find_from_list (logical_file_name, search_list, PR_regular_file, search_type, result))
563 {
564 result = "";
565 }
566
567 return (result);
568}
569
570std::string PathResolver::find_directory (const std::string& logical_file_name,
571 const std::string& search_path,
572 SearchType search_type)
573{
574 const char* path_env = ::getenv (search_path.c_str ());
575
576 std::string path_list;
577
578 if (path_env != 0)
579 {
580 path_list = path_env;
581 }
582
583 return (find_directory_from_list (logical_file_name, path_list, search_type));
584}
585
586std::string PathResolver::find_directory_from_list (const std::string& logical_file_name,
587 const std::string& search_list,
588 SearchType search_type)
589{
590 std::string result;
591
592 if (!PR_find_from_list (logical_file_name, search_list, PR_directory, search_type, result))
593 {
594 result = "";
595 }
596
597 return (result);
598}
599
601{
602 const char* path_env = ::getenv (search_path.c_str ());
603
604 if (path_env == 0) return (EnvironmentVariableUndefined);
605
606#ifdef WIN32
607 static const char path_separator = ';';
608#else
609 static const char path_separator = ':';
610#endif
611
612 std::string path_list (path_env);
613
614 std::string::size_type pos = 0;
615
616 for (int i = 0;;i++)
617 {
618 bool ending = false;
619
620 std::string::size_type next = path_list.find (path_separator, pos);
621
622 std::string path = path_list.substr (pos, next - pos);
623
624 if (next == std::string::npos)
625 {
626 path = path_list.substr (pos);
627 ending = true;
628 }
629 else
630 {
631 path = path_list.substr (pos, next - pos);
632 pos = next + 1;
633 }
634
635 std::string real_name = "";
636
637 if (!PR_test_exist (path, real_name, PR_directory))
638 {
639 return (UnknownDirectory);
640 }
641
642 if (ending) break;
643 }
644
645 return (Ok);
646}
647
648
649
650
651extern "C"
652{
654 {
655 return PathResolver::check_search_path (search_path);
656 }
657
658 std::string PathResolverFindDirectory (const std::string& logical_file_name,
659 const std::string& search_path)
660 {
661 return PathResolver::find_directory (logical_file_name, search_path);
662 }
663
664 std::string PathResolverFindDirectoryFromList (const std::string& logical_file_name,
665 const std::string& search_list)
666 {
667 return PathResolver::find_directory_from_list (logical_file_name, search_list);
668 }
669
670 std::string PathResolverFindFile (const std::string& logical_file_name,
671 const std::string& search_path)
672 {
673 return PathResolver::find_file (logical_file_name, search_path);
674 }
675
676 std::string PathResolverFindFileFromList (const std::string& logical_file_name,
677 const std::string& search_list)
678 {
679 return PathResolver::find_file_from_list (logical_file_name, search_list);
680 }
681
682 std::string PathResolverFindXMLFile (const std::string& logical_file_name)
683 {
684 return PathResolver::find_file (logical_file_name, "XMLPATH");
685 }
686
687 std::string PathResolverFindDataFile (const std::string& logical_file_name)
688 {
689 return PathResolver::find_file (logical_file_name, "DATAPATH");
690 }
691}
const Int_t n
XmlRpcServer s
std::string PathResolverFindDirectory(const std::string &logical_file_name, const std::string &search_path)
std::string PathResolverFindFile(const std::string &logical_file_name, const std::string &search_path)
std::string PathResolverFindDirectoryFromList(const std::string &logical_file_name, const std::string &search_list)
std::string PathResolverFindXMLFile(const std::string &logical_file_name)
PR_search_type
@ PR_recursive
@ PR_local
std::string PathResolverFindFileFromList(const std::string &logical_file_name, const std::string &search_list)
std::string PathResolverFindDataFile(const std::string &logical_file_name)
PR_file_type
@ PR_regular_file
@ PR_directory
PathResolver::SearchPathStatus PathResolverCheckSearchPath(const std::string &search_path)
static std::string find_file(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
static std::string find_directory(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
static std::string find_directory_from_list(const std::string &logical_file_name, const std::string &search_list, SearchType search_type=LocalSearch)
@ EnvironmentVariableUndefined
static std::string find_file_from_list(const std::string &logical_file_name, const std::string &search_list, SearchType search_type=LocalSearch)
static SearchPathStatus check_search_path(const std::string &search_path)
Index next(Index i)