1 : /******************************************************************************
2 : * $Id: cpl_findfile.cpp 20089 2010-07-17 20:42:03Z rouault $
3 : *
4 : * Project: CPL - Common Portability Library
5 : * Purpose: Generic data file location finder, with application hooking.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_multiproc.h"
33 :
34 : CPL_CVSID("$Id: cpl_findfile.cpp 20089 2010-07-17 20:42:03Z rouault $");
35 :
36 : typedef struct
37 : {
38 : int bFinderInitialized;
39 : int nFileFinders;
40 : CPLFileFinder *papfnFinders;
41 : char **papszFinderLocations;
42 : } FindFileTLS;
43 :
44 :
45 : /************************************************************************/
46 : /* CPLFindFileDeinitTLS() */
47 : /************************************************************************/
48 :
49 : static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData);
50 : static CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData);
51 :
52 1974 : static void CPLFindFileFreeTLS(void* pData)
53 : {
54 1974 : FindFileTLS* pTLSData = (FindFileTLS*) pData;
55 1974 : if( pTLSData->bFinderInitialized )
56 : {
57 2067 : while( pTLSData->papszFinderLocations != NULL )
58 1217 : CPLPopFinderLocationInternal(pTLSData);
59 850 : while( CPLPopFileFinderInternal(pTLSData) != NULL ) {}
60 :
61 425 : pTLSData->bFinderInitialized = FALSE;
62 : }
63 1974 : CPLFree(pTLSData);
64 1974 : }
65 :
66 : /************************************************************************/
67 : /* CPLGetFindFileTLS() */
68 : /************************************************************************/
69 :
70 13256 : static FindFileTLS* CPLGetFindFileTLS()
71 : {
72 : FindFileTLS* pTLSData =
73 13256 : (FindFileTLS *) CPLGetTLS( CTLS_FINDFILE );
74 13256 : if (pTLSData == NULL)
75 : {
76 1992 : pTLSData = (FindFileTLS*) CPLCalloc(1, sizeof(FindFileTLS));
77 1992 : CPLSetTLSWithFreeFunc( CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS );
78 : }
79 13256 : return pTLSData;
80 : }
81 :
82 : /************************************************************************/
83 : /* CPLFinderInit() */
84 : /************************************************************************/
85 :
86 6498 : static FindFileTLS* CPLFinderInit()
87 :
88 : {
89 6498 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
90 6498 : if( !pTLSData->bFinderInitialized )
91 : {
92 443 : pTLSData->bFinderInitialized = TRUE;
93 443 : CPLPushFileFinder( CPLDefaultFindFile );
94 :
95 443 : CPLPushFinderLocation( "." );
96 :
97 443 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
98 : {
99 443 : CPLPushFinderLocation( CPLGetConfigOption( "GDAL_DATA", NULL ) );
100 : }
101 : else
102 : {
103 : #ifdef GDAL_PREFIX
104 : #ifdef MACOSX_FRAMEWORK
105 : CPLPushFinderLocation( GDAL_PREFIX "/Resources/gdal" );
106 : #else
107 0 : CPLPushFinderLocation( GDAL_PREFIX "/share/gdal" );
108 : #endif
109 : #else
110 : CPLPushFinderLocation( "/usr/local/share/gdal" );
111 : #endif
112 : }
113 : }
114 6498 : return pTLSData;
115 : }
116 :
117 : /************************************************************************/
118 : /* CPLFinderClean() */
119 : /************************************************************************/
120 :
121 1974 : void CPLFinderClean()
122 :
123 : {
124 1974 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
125 1974 : CPLFindFileFreeTLS(pTLSData);
126 1974 : CPLSetTLS( CTLS_FINDFILE, NULL, FALSE );
127 1974 : }
128 :
129 : /************************************************************************/
130 : /* CPLDefaultFileFind() */
131 : /************************************************************************/
132 :
133 4784 : const char *CPLDefaultFindFile( const char *pszClass,
134 : const char *pszBasename )
135 :
136 : {
137 4784 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
138 4784 : int i, nLocations = CSLCount( pTLSData->papszFinderLocations );
139 :
140 : (void) pszClass;
141 :
142 5166 : for( i = nLocations-1; i >= 0; i-- )
143 : {
144 : const char *pszResult;
145 : VSIStatBuf sStat;
146 :
147 5070 : pszResult = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
148 10140 : NULL );
149 :
150 5070 : if( VSIStat( pszResult, &sStat ) == 0 )
151 4688 : return pszResult;
152 : }
153 :
154 96 : return NULL;
155 : }
156 :
157 : /************************************************************************/
158 : /* CPLFindFile() */
159 : /************************************************************************/
160 :
161 4784 : const char *CPLFindFile( const char *pszClass, const char *pszBasename )
162 :
163 : {
164 : int i;
165 :
166 4784 : FindFileTLS* pTLSData = CPLFinderInit();
167 :
168 4880 : for( i = pTLSData->nFileFinders-1; i >= 0; i-- )
169 : {
170 : const char * pszResult;
171 :
172 4784 : pszResult = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
173 4784 : if( pszResult != NULL )
174 4688 : return pszResult;
175 : }
176 :
177 96 : return NULL;
178 : }
179 :
180 : /************************************************************************/
181 : /* CPLPushFileFinder() */
182 : /************************************************************************/
183 :
184 443 : void CPLPushFileFinder( CPLFileFinder pfnFinder )
185 :
186 : {
187 443 : FindFileTLS* pTLSData = CPLFinderInit();
188 :
189 : pTLSData->papfnFinders = (CPLFileFinder *)
190 443 : CPLRealloc(pTLSData->papfnFinders, sizeof(void*) * ++pTLSData->nFileFinders);
191 443 : pTLSData->papfnFinders[pTLSData->nFileFinders-1] = pfnFinder;
192 443 : }
193 :
194 : /************************************************************************/
195 : /* CPLPopFileFinder() */
196 : /************************************************************************/
197 :
198 850 : CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData)
199 :
200 : {
201 : CPLFileFinder pfnReturn;
202 :
203 850 : if( pTLSData->nFileFinders == 0 )
204 425 : return NULL;
205 :
206 425 : pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
207 :
208 425 : if( pTLSData->nFileFinders == 0)
209 : {
210 425 : CPLFree( pTLSData->papfnFinders );
211 425 : pTLSData->papfnFinders = NULL;
212 : }
213 :
214 425 : return pfnReturn;
215 : }
216 :
217 0 : CPLFileFinder CPLPopFileFinder()
218 :
219 : {
220 0 : return CPLPopFileFinderInternal(CPLFinderInit());
221 : }
222 :
223 : /************************************************************************/
224 : /* CPLPushFinderLocation() */
225 : /************************************************************************/
226 :
227 1271 : void CPLPushFinderLocation( const char *pszLocation )
228 :
229 : {
230 1271 : FindFileTLS* pTLSData = CPLFinderInit();
231 :
232 : pTLSData->papszFinderLocations = CSLAddString( pTLSData->papszFinderLocations,
233 1271 : pszLocation );
234 1271 : }
235 :
236 :
237 : /************************************************************************/
238 : /* CPLPopFinderLocation() */
239 : /************************************************************************/
240 :
241 1217 : static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData)
242 :
243 : {
244 : int nCount;
245 :
246 1217 : if( pTLSData->papszFinderLocations == NULL )
247 0 : return;
248 :
249 1217 : nCount = CSLCount(pTLSData->papszFinderLocations);
250 1217 : if( nCount == 0 )
251 0 : return;
252 :
253 1217 : CPLFree( pTLSData->papszFinderLocations[nCount-1] );
254 1217 : pTLSData->papszFinderLocations[nCount-1] = NULL;
255 :
256 1217 : if( nCount == 1 )
257 : {
258 425 : CPLFree( pTLSData->papszFinderLocations );
259 425 : pTLSData->papszFinderLocations = NULL;
260 : }
261 : }
262 :
263 0 : void CPLPopFinderLocation()
264 : {
265 0 : CPLPopFinderLocationInternal(CPLFinderInit());
266 0 : }
|