1 : /******************************************************************************
2 : * $Id: cpl_findfile.cpp 17143 2009-05-28 18:26:05Z 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 17143 2009-05-28 18:26:05Z rouault $");
35 :
36 : typedef struct
37 : {
38 : int bFinderInitialized;
39 : int nFileFinders;
40 : CPLFileFinder *papfnFinders;
41 : char **papszFinderLocations;
42 : } FindFileTLS;
43 :
44 :
45 : /************************************************************************/
46 : /* CPLGetFindFileTLS() */
47 : /************************************************************************/
48 :
49 2567 : static FindFileTLS* CPLGetFindFileTLS()
50 : {
51 : FindFileTLS* pTLSData =
52 2567 : (FindFileTLS *) CPLGetTLS( CTLS_FINDFILE );
53 2567 : if (pTLSData == NULL)
54 : {
55 727 : pTLSData = (FindFileTLS*) CPLCalloc(1, sizeof(FindFileTLS));
56 727 : CPLSetTLS( CTLS_FINDFILE, pTLSData, TRUE );
57 : }
58 2567 : return pTLSData;
59 : }
60 :
61 : /************************************************************************/
62 : /* CPLFinderInit() */
63 : /************************************************************************/
64 :
65 1359 : static FindFileTLS* CPLFinderInit()
66 :
67 : {
68 1359 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
69 1359 : if( !pTLSData->bFinderInitialized )
70 : {
71 107 : pTLSData->bFinderInitialized = TRUE;
72 107 : CPLPushFileFinder( CPLDefaultFindFile );
73 :
74 107 : CPLPushFinderLocation( "." );
75 :
76 107 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
77 : {
78 107 : CPLPushFinderLocation( CPLGetConfigOption( "GDAL_DATA", NULL ) );
79 : }
80 : else
81 : {
82 : #ifdef GDAL_PREFIX
83 : #ifdef MACOSX_FRAMEWORK
84 : CPLPushFinderLocation( GDAL_PREFIX "/Resources/gdal" );
85 : #else
86 0 : CPLPushFinderLocation( GDAL_PREFIX "/share/gdal" );
87 : #endif
88 : #else
89 : CPLPushFinderLocation( "/usr/local/share/gdal" );
90 : #endif
91 : }
92 : }
93 1359 : return pTLSData;
94 : }
95 :
96 : /************************************************************************/
97 : /* CPLFinderClean() */
98 : /************************************************************************/
99 :
100 719 : void CPLFinderClean()
101 :
102 : {
103 719 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
104 719 : if( pTLSData->bFinderInitialized )
105 : {
106 468 : while( pTLSData->papszFinderLocations != NULL )
107 270 : CPLPopFinderLocation();
108 198 : while( CPLPopFileFinder() != NULL ) {}
109 :
110 99 : pTLSData->bFinderInitialized = FALSE;
111 : }
112 719 : }
113 :
114 : /************************************************************************/
115 : /* CPLDefaultFileFind() */
116 : /************************************************************************/
117 :
118 : const char *CPLDefaultFindFile( const char *pszClass,
119 489 : const char *pszBasename )
120 :
121 : {
122 489 : FindFileTLS* pTLSData = CPLGetFindFileTLS();
123 489 : int i, nLocations = CSLCount( pTLSData->papszFinderLocations );
124 :
125 : (void) pszClass;
126 :
127 508 : for( i = nLocations-1; i >= 0; i-- )
128 : {
129 : const char *pszResult;
130 : VSIStatBuf sStat;
131 :
132 : pszResult = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
133 503 : NULL );
134 :
135 503 : if( VSIStat( pszResult, &sStat ) == 0 )
136 484 : return pszResult;
137 : }
138 :
139 5 : return NULL;
140 : }
141 :
142 : /************************************************************************/
143 : /* CPLFindFile() */
144 : /************************************************************************/
145 :
146 489 : const char *CPLFindFile( const char *pszClass, const char *pszBasename )
147 :
148 : {
149 : int i;
150 :
151 489 : FindFileTLS* pTLSData = CPLFinderInit();
152 :
153 494 : for( i = pTLSData->nFileFinders-1; i >= 0; i-- )
154 : {
155 : const char * pszResult;
156 :
157 489 : pszResult = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
158 489 : if( pszResult != NULL )
159 484 : return pszResult;
160 : }
161 :
162 5 : return NULL;
163 : }
164 :
165 : /************************************************************************/
166 : /* CPLPushFileFinder() */
167 : /************************************************************************/
168 :
169 107 : void CPLPushFileFinder( CPLFileFinder pfnFinder )
170 :
171 : {
172 107 : FindFileTLS* pTLSData = CPLFinderInit();
173 :
174 : pTLSData->papfnFinders = (CPLFileFinder *)
175 107 : CPLRealloc(pTLSData->papfnFinders, sizeof(void*) * ++pTLSData->nFileFinders);
176 107 : pTLSData->papfnFinders[pTLSData->nFileFinders-1] = pfnFinder;
177 107 : }
178 :
179 : /************************************************************************/
180 : /* CPLPopFileFinder() */
181 : /************************************************************************/
182 :
183 198 : CPLFileFinder CPLPopFileFinder()
184 :
185 : {
186 : CPLFileFinder pfnReturn;
187 :
188 198 : FindFileTLS* pTLSData = CPLFinderInit();
189 :
190 198 : if( pTLSData->nFileFinders == 0 )
191 99 : return NULL;
192 :
193 99 : pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
194 :
195 99 : if( pTLSData->nFileFinders == 0)
196 : {
197 99 : CPLFree( pTLSData->papfnFinders );
198 99 : pTLSData->papfnFinders = NULL;
199 : }
200 :
201 99 : return pfnReturn;
202 : }
203 :
204 : /************************************************************************/
205 : /* CPLPushFinderLocation() */
206 : /************************************************************************/
207 :
208 295 : void CPLPushFinderLocation( const char *pszLocation )
209 :
210 : {
211 295 : FindFileTLS* pTLSData = CPLFinderInit();
212 :
213 : pTLSData->papszFinderLocations = CSLAddString( pTLSData->papszFinderLocations,
214 295 : pszLocation );
215 295 : }
216 :
217 :
218 : /************************************************************************/
219 : /* CPLPopFinderLocation() */
220 : /************************************************************************/
221 :
222 270 : void CPLPopFinderLocation()
223 :
224 : {
225 : int nCount;
226 :
227 270 : FindFileTLS* pTLSData = CPLFinderInit();
228 :
229 270 : if( pTLSData->papszFinderLocations == NULL )
230 0 : return;
231 :
232 270 : nCount = CSLCount(pTLSData->papszFinderLocations);
233 270 : if( nCount == 0 )
234 0 : return;
235 :
236 270 : CPLFree( pTLSData->papszFinderLocations[nCount-1] );
237 270 : pTLSData->papszFinderLocations[nCount-1] = NULL;
238 :
239 270 : if( nCount == 1 )
240 : {
241 99 : CPLFree( pTLSData->papszFinderLocations );
242 99 : pTLSData->papszFinderLocations = NULL;
243 : }
244 : }
|