xref: /netbsd-src/external/bsd/elftosb/dist/common/SearchPath.cpp (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
1*993229b6Sjkunz /*
2*993229b6Sjkunz  * File:	SearchPath.cpp
3*993229b6Sjkunz  *
4*993229b6Sjkunz  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5*993229b6Sjkunz  * See included license file for license details.
6*993229b6Sjkunz  */
7*993229b6Sjkunz 
8*993229b6Sjkunz #include "SearchPath.h"
9*993229b6Sjkunz #include <stdio.h>
10*993229b6Sjkunz 
11*993229b6Sjkunz #if defined(WIN32)
12*993229b6Sjkunz 	#define PATH_SEP_CHAR '\\'
13*993229b6Sjkunz 	#define PATH_SEP_STRING "\\"
14*993229b6Sjkunz #else
15*993229b6Sjkunz 	#define PATH_SEP_CHAR '/'
16*993229b6Sjkunz 	#define PATH_SEP_STRING "/"
17*993229b6Sjkunz #endif
18*993229b6Sjkunz 
19*993229b6Sjkunz PathSearcher * PathSearcher::s_searcher = NULL;
20*993229b6Sjkunz 
21*993229b6Sjkunz //! This function will create the global path search object if it has
22*993229b6Sjkunz //! not already been created.
getGlobalSearcher()23*993229b6Sjkunz PathSearcher & PathSearcher::getGlobalSearcher()
24*993229b6Sjkunz {
25*993229b6Sjkunz 	if (!s_searcher)
26*993229b6Sjkunz 	{
27*993229b6Sjkunz 		s_searcher = new PathSearcher;
28*993229b6Sjkunz 	}
29*993229b6Sjkunz 
30*993229b6Sjkunz 	return *s_searcher;
31*993229b6Sjkunz }
32*993229b6Sjkunz 
addSearchPath(std::string & path)33*993229b6Sjkunz void PathSearcher::addSearchPath(std::string & path)
34*993229b6Sjkunz {
35*993229b6Sjkunz 	m_paths.push_back(path);
36*993229b6Sjkunz }
37*993229b6Sjkunz 
38*993229b6Sjkunz //! The \a base path argument can be either a relative or absolute path. If the path
39*993229b6Sjkunz //! is relative, then it is joined with search paths one after another until a matching
40*993229b6Sjkunz //! file is located or all search paths are exhausted. If the \a base is absolute,
41*993229b6Sjkunz //! only that path is tested and if invalid false is returned.
42*993229b6Sjkunz //!
43*993229b6Sjkunz //! \param base A path to the file that is to be found.
44*993229b6Sjkunz //! \param targetType Currently ignored. In the future it will let you select whether to
45*993229b6Sjkunz //!		find a file or directory.
46*993229b6Sjkunz //! \param searchCwd If set to true, the current working directory is searched before using
47*993229b6Sjkunz //!		any of the search paths. Otherwise only the search paths are considered.
48*993229b6Sjkunz //! \param[out] result When true is returned this string is set to the first path at which
49*993229b6Sjkunz //!		a valid file was found.
50*993229b6Sjkunz //!
51*993229b6Sjkunz //! \retval true A matching file was found among the search paths. The contents of \a result
52*993229b6Sjkunz //!		are a valid path.
53*993229b6Sjkunz //! \retval false No match could be made. \a result has been left unmodified.
search(const std::string & base,target_type_t targetType,bool searchCwd,std::string & result)54*993229b6Sjkunz bool PathSearcher::search(const std::string & base, target_type_t targetType, bool searchCwd, std::string & result)
55*993229b6Sjkunz {
56*993229b6Sjkunz 	FILE * tempFile;
57*993229b6Sjkunz 	bool absolute = isAbsolute(base);
58*993229b6Sjkunz 
59*993229b6Sjkunz 	// Try cwd first if requested. Same process applies to absolute paths.
60*993229b6Sjkunz 	if (absolute || searchCwd)
61*993229b6Sjkunz 	{
62*993229b6Sjkunz 		tempFile = fopen(base.c_str(), "r");
63*993229b6Sjkunz 		if (tempFile)
64*993229b6Sjkunz 		{
65*993229b6Sjkunz 			fclose(tempFile);
66*993229b6Sjkunz 			result = base;
67*993229b6Sjkunz 			return true;
68*993229b6Sjkunz 		}
69*993229b6Sjkunz 	}
70*993229b6Sjkunz 
71*993229b6Sjkunz 	// If the base path is absolute and the previous test failed, then we don't go any further.
72*993229b6Sjkunz 	if (absolute)
73*993229b6Sjkunz 	{
74*993229b6Sjkunz 		return false;
75*993229b6Sjkunz 	}
76*993229b6Sjkunz 
77*993229b6Sjkunz 	// Iterate over all search paths.
78*993229b6Sjkunz 	string_list_t::const_iterator it = m_paths.begin();
79*993229b6Sjkunz 	for (; it != m_paths.end(); ++it)
80*993229b6Sjkunz 	{
81*993229b6Sjkunz 		std::string searchPath = joinPaths(*it, base);
82*993229b6Sjkunz 
83*993229b6Sjkunz 		tempFile = fopen(searchPath.c_str(), "r");
84*993229b6Sjkunz 		if (tempFile)
85*993229b6Sjkunz 		{
86*993229b6Sjkunz 			fclose(tempFile);
87*993229b6Sjkunz 			result = searchPath;
88*993229b6Sjkunz 			return true;
89*993229b6Sjkunz 		}
90*993229b6Sjkunz 	}
91*993229b6Sjkunz 
92*993229b6Sjkunz 	// Couldn't find anything matching the base path.
93*993229b6Sjkunz 	return false;
94*993229b6Sjkunz }
95*993229b6Sjkunz 
isAbsolute(const std::string & path)96*993229b6Sjkunz bool PathSearcher::isAbsolute(const std::string & path)
97*993229b6Sjkunz {
98*993229b6Sjkunz #if __WIN32__
99*993229b6Sjkunz 	return path.size() >= 3 && path[1] == ':' && path[2] == '\\';
100*993229b6Sjkunz #else
101*993229b6Sjkunz 	return path.size() >= 1 && path[0] == '/';
102*993229b6Sjkunz #endif
103*993229b6Sjkunz }
104*993229b6Sjkunz 
joinPaths(const std::string & first,const std::string & second)105*993229b6Sjkunz std::string PathSearcher::joinPaths(const std::string & first, const std::string & second)
106*993229b6Sjkunz {
107*993229b6Sjkunz 	// Start with first string.
108*993229b6Sjkunz 	std::string result = first;
109*993229b6Sjkunz 
110*993229b6Sjkunz 	// Add path separator if needed
111*993229b6Sjkunz 	if ((first[first.size() - 1] != PATH_SEP_CHAR) && (second[0] != PATH_SEP_CHAR))
112*993229b6Sjkunz 	{
113*993229b6Sjkunz 		result += PATH_SEP_STRING;
114*993229b6Sjkunz 	}
115*993229b6Sjkunz 
116*993229b6Sjkunz 	// Append the second string.
117*993229b6Sjkunz 	result += second;
118*993229b6Sjkunz 
119*993229b6Sjkunz 	// And return the whole mess.
120*993229b6Sjkunz 	return result;
121*993229b6Sjkunz }
122