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