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 1033 : static void CPLFindFileFreeTLS(void* pData)
53 : {
54 1033 : FindFileTLS* pTLSData = (FindFileTLS*) pData;
55 1033 : if( pTLSData->bFinderInitialized )
56 : {
57 1189 : while( pTLSData->papszFinderLocations != NULL )
58 701 : CPLPopFinderLocationInternal(pTLSData);
59 488 : while( CPLPopFileFinderInternal(pTLSData) != NULL ) {}
60 :
61 244 : pTLSData->bFinderInitialized = FALSE;
62 : }
63 1033 : CPLFree(pTLSData);
64 1033 : }
65 :
66 : /************************************************************************/
67 : /* CPLGetFindFileTLS() */
68 : /************************************************************************/
69 :
70 7162 : static FindFileTLS* CPLGetFindFileTLS()
71 : {
72 : FindFileTLS* pTLSData =
73 7162 : (FindFileTLS *) CPLGetTLS( CTLS_FINDFILE );
74 7162 : if (pTLSData == NULL)
75 : {
76 1044 : pTLSData = (FindFileTLS*) CPLCalloc(1, sizeof(FindFileTLS));
77 1044 : CPLSetTLSWithFreeFunc( CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS );
78 : }
79 7162 : return pTLSData;
80 : }
81 :
82 : /************************************************************************/
83 : /* CPLFinderInit() */
84 : /************************************************************************/
85 :
86 3559 : static FindFileTLS* CPLFinderInit()
87 :
88 : {
89 3559 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
90 3559 : if( !pTLSData->bFinderInitialized )
91 : {
92 255 : pTLSData->bFinderInitialized = TRUE;
93 255 : CPLPushFileFinder( CPLDefaultFindFile );
94 :
95 255 : CPLPushFinderLocation( "." );
96 :
97 255 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
98 : {
99 255 : 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 3559 : return pTLSData;
115 : }
116 :
117 : /************************************************************************/
118 : /* CPLFinderClean() */
119 : /************************************************************************/
120 :
121 1033 : void CPLFinderClean()
122 :
123 : {
124 1033 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
125 1033 : CPLFindFileFreeTLS(pTLSData);
126 1033 : CPLSetTLS( CTLS_FINDFILE, NULL, FALSE );
127 1033 : }
128 :
129 : /************************************************************************/
130 : /* CPLDefaultFileFind() */
131 : /************************************************************************/
132 :
133 2570 : const char *CPLDefaultFindFile( const char *pszClass,
134 : const char *pszBasename )
135 :
136 : {
137 2570 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
138 2570 : int i, nLocations = CSLCount( pTLSData->papszFinderLocations );
139 :
140 : (void) pszClass;
141 :
142 2757 : for( i = nLocations-1; i >= 0; i-- )
143 : {
144 : const char *pszResult;
145 : VSIStatBuf sStat;
146 :
147 2710 : pszResult = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
148 5420 : NULL );
149 :
150 2710 : if( VSIStat( pszResult, &sStat ) == 0 )
151 2523 : return pszResult;
152 : }
153 :
154 47 : return NULL;
155 : }
156 :
157 : /************************************************************************/
158 : /* CPLFindFile() */
159 : /************************************************************************/
160 :
161 2570 : const char *CPLFindFile( const char *pszClass, const char *pszBasename )
162 :
163 : {
164 : int i;
165 :
166 2570 : FindFileTLS* pTLSData = CPLFinderInit();
167 :
168 2617 : for( i = pTLSData->nFileFinders-1; i >= 0; i-- )
169 : {
170 : const char * pszResult;
171 :
172 2570 : pszResult = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
173 2570 : if( pszResult != NULL )
174 2523 : return pszResult;
175 : }
176 :
177 47 : return NULL;
178 : }
179 :
180 : /************************************************************************/
181 : /* CPLPushFileFinder() */
182 : /************************************************************************/
183 :
184 255 : void CPLPushFileFinder( CPLFileFinder pfnFinder )
185 :
186 : {
187 255 : FindFileTLS* pTLSData = CPLFinderInit();
188 :
189 : pTLSData->papfnFinders = (CPLFileFinder *)
190 255 : CPLRealloc(pTLSData->papfnFinders, sizeof(void*) * ++pTLSData->nFileFinders);
191 255 : pTLSData->papfnFinders[pTLSData->nFileFinders-1] = pfnFinder;
192 255 : }
193 :
194 : /************************************************************************/
195 : /* CPLPopFileFinder() */
196 : /************************************************************************/
197 :
198 488 : CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData)
199 :
200 : {
201 : CPLFileFinder pfnReturn;
202 :
203 488 : if( pTLSData->nFileFinders == 0 )
204 244 : return NULL;
205 :
206 244 : pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
207 :
208 244 : if( pTLSData->nFileFinders == 0)
209 : {
210 244 : CPLFree( pTLSData->papfnFinders );
211 244 : pTLSData->papfnFinders = NULL;
212 : }
213 :
214 244 : return pfnReturn;
215 : }
216 :
217 0 : CPLFileFinder CPLPopFileFinder()
218 :
219 : {
220 0 : return CPLPopFileFinderInternal(CPLFinderInit());
221 : }
222 :
223 : /************************************************************************/
224 : /* CPLPushFinderLocation() */
225 : /************************************************************************/
226 :
227 734 : void CPLPushFinderLocation( const char *pszLocation )
228 :
229 : {
230 734 : FindFileTLS* pTLSData = CPLFinderInit();
231 :
232 : pTLSData->papszFinderLocations = CSLAddString( pTLSData->papszFinderLocations,
233 734 : pszLocation );
234 734 : }
235 :
236 :
237 : /************************************************************************/
238 : /* CPLPopFinderLocation() */
239 : /************************************************************************/
240 :
241 701 : static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData)
242 :
243 : {
244 : int nCount;
245 :
246 701 : if( pTLSData->papszFinderLocations == NULL )
247 0 : return;
248 :
249 701 : nCount = CSLCount(pTLSData->papszFinderLocations);
250 701 : if( nCount == 0 )
251 0 : return;
252 :
253 701 : CPLFree( pTLSData->papszFinderLocations[nCount-1] );
254 701 : pTLSData->papszFinderLocations[nCount-1] = NULL;
255 :
256 701 : if( nCount == 1 )
257 : {
258 244 : CPLFree( pTLSData->papszFinderLocations );
259 244 : pTLSData->papszFinderLocations = NULL;
260 : }
261 : }
262 :
263 0 : void CPLPopFinderLocation()
264 : {
265 0 : CPLPopFinderLocationInternal(CPLFinderInit());
266 0 : }
|