/[ascend]/trunk/base/generic/utilities/ascDynaLoad.c
ViewVC logotype

Annotation of /trunk/base/generic/utilities/ascDynaLoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1949 - (hide annotations) (download) (as text)
Mon Nov 10 01:41:41 2008 UTC (14 years, 2 months ago) by jpye
File MIME type: text/x-csrc
File size: 18591 byte(s)
Fixed tcl-config for Windows (working with ActiveState Tcl 8.4)
Removed debug output from ascDynaload.
1 johnpye 478 /* ASCEND modelling environment
2     Copyright (C) 2006 Carnegie Mellon University
3 aw0a 1
4 johnpye 478 This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2, or (at your option)
7     any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place - Suite 330,
17     Boston, MA 02111-1307, USA.
18 johnpye 791 *//**
19     @file
20    
21 johnpye 427 This file *should* support unix/linux-style systems (dlfcn.h)
22     and Windows.
23 aw0a 1
24 johnpye 427 Note that under many systems, profiling does not work
25     with dynamic libraries!
26 johnpye 158 */
27    
28 aw0a 1 #include <stdio.h>
29     #include <stdlib.h>
30 ben.allan 45 #include <stdarg.h>
31 johnpye 399 #include "ascConfig.h"
32     #include "error.h"
33     #include "ascPrint.h"
34     #include "ascPanic.h"
35     #include "ascMalloc.h"
36     #include "ascDynaLoad.h"
37 johnpye 862 #include "ascEnvVar.h"
38 jds 59
39 johnpye 791 #include <general/env.h>
40     #include <general/ospath.h>
41 johnpye 399 #include <compiler/instance_enum.h>
42     #include <general/list.h>
43     #include <compiler/extfunc.h>
44 johnpye 862 #include <compiler/importhandler.h>
45 johnpye 380
46 johnpye 466 typedef int (*ExternalLibraryRegister_fptr_t)(void);
47 johnpye 380
48 johnpye 158 /*--------------------------------------
49     GENERIC STUFF
50     */
51    
52 aw0a 1 struct ascend_dlrecord {
53 jds 59 char *path; /* library name */
54 aw0a 1 void *dlreturn; /* return from dlopen */
55     struct ascend_dlrecord *next;
56     };
57    
58 jds 59 /* Linked list of library names & dlopen() return values. */
59 johnpye 791 static struct ascend_dlrecord *g_ascend_dllist = NULL;
60 aw0a 1
61     /*
62 jds 59 * Adds a record of the path and handle to the list.
63     * If it fails to do this, returns 1, else 0.
64 aw0a 1 */
65 johnpye 791 static int AscAddRecord(void *dlreturn, CONST char *path){
66 aw0a 1 struct ascend_dlrecord *new;
67     char *keeppath;
68     if (dlreturn == NULL || path == NULL) {
69     return 1;
70     }
71 johnpye 1220 keeppath = ASC_STRDUP((char *)path);
72 aw0a 1 if (keeppath==NULL) return 1;
73 johnpye 709 new = ASC_NEW(struct ascend_dlrecord);
74 aw0a 1 if (new==NULL) {
75 jds 103 ascfree(keeppath);
76 aw0a 1 return 1;
77     }
78     new->next = g_ascend_dllist; /* insert at head */
79     g_ascend_dllist = new;
80     new->path = keeppath;
81     new->dlreturn = dlreturn;
82     return 0;
83     }
84    
85     /*
86     * Finds a record of the path given and returns the associated handle.
87     * If it fails to do this, returns NULL.
88     */
89     static
90     void *AscFindDLRecord(CONST char *path)
91     {
92     struct ascend_dlrecord *new;
93     if (path == NULL) {
94     return NULL;
95     }
96     new = g_ascend_dllist;
97     while (new != NULL && strcmp(new->path,path) != 0) {
98     /* advance new until no more new or new with path found */
99     new = new->next;
100     }
101     return (new != NULL) ? new->dlreturn : NULL;
102     }
103    
104     /*
105     * Finds and returns the handle to path, if one matches, and
106 jds 59 * deletes the record from the list. Returns NULL if not found.
107 aw0a 1 */
108     static
109 jds 103 void *AscDeleteRecord(CONST char *path)
110 aw0a 1 {
111     struct ascend_dlrecord *nextptr, *lastptr, *old;
112     void *dlreturn = NULL;
113 jds 59
114 jds 61 if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL;
115 jds 59
116 aw0a 1 if (strcmp(path,g_ascend_dllist->path)==0) {
117     /* head case */
118     old = g_ascend_dllist;
119     g_ascend_dllist = old->next;
120     dlreturn = old->dlreturn;
121 jds 103 ascfree(old->path);
122     ascfree(old);
123 aw0a 1 } else {
124     lastptr = g_ascend_dllist;
125     nextptr = lastptr->next;
126     while (nextptr != NULL && strcmp(nextptr->path,path) != 0) {
127     lastptr = nextptr;
128     nextptr = nextptr->next;
129     }
130     /* so either nextptr is NULL and not in list, or nextptr is
131     * what we want to delete and lastptr is the link to it.
132     */
133     if (nextptr != NULL) {
134     old = nextptr;
135     lastptr->next = nextptr->next;
136     dlreturn = old->dlreturn;
137 jds 103 ascfree(old->path);
138     ascfree(old);
139 aw0a 1 }
140     }
141     return dlreturn;
142     }
143    
144     /*
145 jds 59 * Checks the list for a conflicting handle so we can issue
146 aw0a 1 * a more helpful warning, if need be, than the standard message.
147     */
148 jds 59 static
149 aw0a 1 void AscCheckDuplicateLoad(CONST char *path)
150     {
151     struct ascend_dlrecord *r;
152 jds 59
153     if (NULL == path) {
154 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Null path");
155 jds 59 return;
156     }
157    
158 aw0a 1 r = g_ascend_dllist;
159     while (r != NULL) {
160     if (strcmp(path,r->path)==0) {
161 johnpye 972 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Attempt to load already loaded '%s'.",path);
162 aw0a 1 return;
163     }
164     r = r->next;
165     }
166     }
167    
168 johnpye 791
169 johnpye 427 /*-----------------------------------------------
170     WINDOWS
171 johnpye 158 */
172 johnpye 427 #if defined(__WIN32__)
173     # include <windows.h>
174 johnpye 158
175 johnpye 485 int Asc_DynamicLoad(CONST char *path, CONST char *initFun){
176 aw0a 1 HINSTANCE xlib;
177 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
178 aw0a 1
179 jds 59 if (NULL == path) {
180 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null path\n");
181 jds 59 return 1;
182     }
183    
184 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
185     /*
186     * If the named library does not exist, if it's not loadable or if
187     * it does not define the named install proc, report an error
188     */
189    
190     xlib = LoadLibrary(path);
191     if (xlib == NULL) {
192 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"LoadLibrary failed\n'%s'",path);
193 aw0a 1 return 1;
194     }
195 jpye 1949 #if 0
196 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"LoadLibrary succeeded, '%s'\n",path);
197 jpye 1949 #endif
198 johnpye 543
199 jds 59 if (NULL != initFun) {
200 wangym 489 install = (int (*)(void))GetProcAddress(xlib,initFun);
201 jds 59 if (install == NULL) {
202 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Required function '%s' not found", initFun);
203 jds 59 (void)FreeLibrary(xlib);
204     return 1;
205 jpye 1597 #if 0
206     }else{
207 johnpye 66 FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install);
208 jpye 1597 #endif
209 johnpye 62 }
210 aw0a 1 }
211 jds 59 if (0 != AscAddRecord(xlib,path)) {
212 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)\n",path);
213 aw0a 1 }
214 johnpye 466 return (install == NULL) ? 0 : (*install)();
215 aw0a 1 }
216 johnpye 485 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
217 johnpye 427
218     # define UNLOAD FreeLibrary
219     # define DLLSYM GetProcAddress
220     # define DLL_CAST (HINSTANCE)
221     # define ASC_DLERRSTRING "unknown"
222     # define UNLOAD_SUCCESS TRUE
223    
224 aw0a 1 #endif /* __WIN32__ */
225 jds 61
226 johnpye 427 /*-----------------------------------------------
227     UNIX/LINUX
228     */
229 johnpye 62 /*
230     SOLARIS and LINUX
231     */
232 johnpye 158 /* NOTE, added defined(__unix__) here, not sure if that's a bad thing or not -- johnpye */
233 johnpye 62 /*
234 johnpye 190 From a quick Google, it appears that AIX 5.1 now provides dlfcn.h,
235 johnpye 158 so I'll remove the code that was emulating it here. -- johnpye
236 johnpye 62 */
237 jpye 1662 #if (defined(sun) || defined(linux) || defined(__unix__) || defined(solaris) \
238     || defined(_AIX) || defined(_SGI_SOURCE) || defined(__APPLE__))
239 johnpye 158 # ifndef MACH
240     # include <dlfcn.h>
241     # else
242     # error "MACH unsupported"
243 ben.allan 467 # endif /* mach */
244 jds 59
245 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
246     {
247     void *xlib;
248 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
249 jds 59
250     if (NULL == path) {
251 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null path");
252 jds 59 return 1;
253     }
254    
255 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
256    
257     /*
258     * If the named library does not exist, if it's not loadable or if
259     * it does not define the named install proc, report an error
260     */
261     xlib = dlopen(path, 1);
262 jds 61 if (xlib == NULL) {
263 jpye 1598 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s",(char *)dlerror());
264    
265     #ifdef linux
266     ERROR_REPORTER_HERE(ASC_PROG_ERR,"LD_LIBRARY_PATH = \"%s\"",getenv("LD_LIBRARY_PATH"));
267     #endif
268    
269 aw0a 1 return 1;
270     }
271 jds 61 if (NULL != initFun) {
272 johnpye 1228 /* https://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=2252 */
273     *(void**)(&install) = dlsym(xlib, initFun);
274 jds 61 if (install == NULL) {
275 jpye 1628 ERROR_REPORTER_HERE(ASC_PROG_ERR,"While attempting to run '%s' in '%s': %s",initFun, path, (char *)dlerror());
276 jds 61 dlclose(xlib);
277     return 1;
278     }
279     }
280 johnpye 190
281 jds 59 if (0 != AscAddRecord(xlib,path)) {
282 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)",path);
283 aw0a 1 }
284 johnpye 466 return (install == NULL) ? 0 : (*install)();
285 aw0a 1 }
286 johnpye 485 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
287 aw0a 1
288 johnpye 427 # define UNLOAD dlclose
289     # define DLLSYM dlsym
290     # define DLL_CAST (void *)
291     # define ASC_DLERRSTRING dlerror()
292     # define UNLOAD_SUCCESS 0
293    
294 johnpye 158 #endif /* posix: linux, unix, solaris,sgi */
295 aw0a 1
296 johnpye 427 /*-----------------------------------------------
297     HPUX
298     */
299 aw0a 1 #ifdef __hpux
300     /*
301 johnpye 427 Kirk Abbott last fiddled with the following, which was
302     originally put in place my Michael Moore for an
303     HP/UX 9.X Operating Sys back in 1993. Arrr. No idea if
304     it still works.
305     */
306 aw0a 1
307 johnpye 158 # include <dl.h>
308     # include <errno.h>
309 aw0a 1
310     int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
311     {
312     shl_t xlib;
313 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
314 aw0a 1 int i;
315 jds 59
316     if (NULL == path) {
317 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null path");
318 jds 59 return 1;
319     }
320    
321 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
322    
323     /*
324     * If the named library does not exist, if it's not loadable or if
325     * it does not define the named install proc, report an error
326     */
327     xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
328     if (xlib == (shl_t) NULL) {
329 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to load shared library: %s",strerror(errno));
330 aw0a 1 return 1;
331     }
332 jds 59 if (NULL != initFun) {
333     i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
334     if (i == -1) {
335 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find needed symbol '%s': %s",
336 jds 59 initFun, strerror(errno));
337     shl_unload(xlib); /* baa */
338     return 1;
339 aw0a 1 }
340 johnpye 790 if(install == NULL) {
341     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find needed symbol '%s'. Error type unknown",initFun);
342 jds 59 shl_unload(xlib); /* baa */
343     return 1;
344     }
345 aw0a 1 }
346 jds 59 if (0 != AscAddRecord(xlib,path)) {
347 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)",path);
348 aw0a 1 }
349 johnpye 466 return (install == NULL) ? 0 : (*install)();
350 aw0a 1 }
351 johnpye 485 # define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
352 aw0a 1
353 johnpye 158 # define UNLOAD shl_unload
354     # define DLL_CAST (shl_t)
355     # define ASC_DLERRSTRING "NULL definition"
356     # define UNLOAD_SUCCESS 0
357 johnpye 427
358 aw0a 1 #endif /* __hpux */
359    
360 johnpye 427 /*-----------------------------------------------
361     Did we get something from the above?
362 johnpye 158 */
363    
364 johnpye 478 #ifndef ASCDL_OK
365 johnpye 427 # error "Unable to define an Asc_DynamicLoad function. Check your compiler options and installed system libraries."
366     #endif
367    
368     /**-----------------------------------------------
369     DYNAMIC UNLOADING
370     */
371    
372 jds 103 int Asc_DynamicUnLoad(CONST char *path)
373 aw0a 1 {
374     void *dlreturn;
375 jds 61 int retval;
376 johnpye 190
377 jds 59 if (NULL == path) {
378 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR, "Failed: Null path");
379 jds 59 return -3;
380     }
381    
382 aw0a 1 dlreturn = AscDeleteRecord(path);
383     if (dlreturn == NULL) {
384 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR, "Unable to remember or unload %s", path);
385 aw0a 1 return -3;
386     }
387 johnpye 790 CONSOLE_DEBUG("Asc_DynamicUnLoad: forgetting & unloading %s", path);
388 johnpye 190 /*
389 jds 61 * dlclose() returns 0 on success, FreeLibrary() returns TRUE.
390     * A uniform convention is preferable, so trap and return 0 on success.
391     */
392     retval = UNLOAD(DLL_CAST dlreturn);
393     return (retval == UNLOAD_SUCCESS) ? 0 : retval;
394 aw0a 1 }
395    
396 johnpye 427 /**-----------------------------------------------
397     DYNAMIC VARIABLE LINKING
398     */
399 jds 103 void *Asc_DynamicVariable(CONST char *libname, CONST char *symbol)
400 aw0a 1 {
401     void *dlreturn;
402     void *symreturn;
403     #ifdef __hpux
404     int i;
405     #endif
406    
407 jds 59 if (libname == NULL) {
408 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null libname");
409 aw0a 1 return NULL;
410     }
411 jds 59 if (symbol == NULL) {
412 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null symbol");
413 jds 59 return NULL;
414     }
415    
416 aw0a 1 dlreturn = AscFindDLRecord(libname);
417     if (dlreturn == NULL) {
418 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested library %s", libname);
419 aw0a 1 return NULL;
420     }
421     #ifdef __hpux
422     i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
423     if (i == -1) {
424 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested symbol '%s' in %s (%s)",
425 aw0a 1 symbol, libname, strerror(errno));
426     symreturn = NULL;
427     }
428 jds 103 #elif defined(__WIN32__)
429     /*
430     * Here's a bit of possibly-misdirected casting horror.
431     * ISO C forbids casting between function and data pointers, so, naturally,
432     * we cast between function and data pointers. Well, we don't have much
433     * choice. GetProcAddress() returns a function pointer for both functions
434 johnpye 190 * and variables so we have to do the cast for variables. This is ok on
435     * 32 bit Windows since the pointers are compatible. Then, to avoid
436     * being reminded by the compiler that we're doing something illegal,
437 jds 103 * we apply convoluted casting to shut it up.
438     * Oh, the crap you can find on the internet... JDS
439     */
440     *(FARPROC*)(&symreturn) = GetProcAddress((HINSTANCE)dlreturn, symbol);
441 aw0a 1 #else
442 jds 103 /* no problem on POSIX systems - dlsym() returns a void *. */
443     symreturn = dlsym(dlreturn, symbol);
444 aw0a 1 #endif
445     if (symreturn == NULL) {
446 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested symbol '%s' in %s",symbol,libname);
447     ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type: %s",ASC_DLERRSTRING);
448 aw0a 1 }
449     return symreturn;
450     }
451 jds 103
452 johnpye 427 /**-----------------------------------------------
453     DYNAMIC FUNCTION LINKING
454     */
455 jds 103 DynamicF Asc_DynamicFunction(CONST char *libname, CONST char *symbol)
456     {
457     void *dlreturn;
458     DynamicF symreturn;
459     #ifdef __hpux
460     int i;
461     #endif
462    
463     if (libname == NULL) {
464 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null library name");
465 jds 103 return NULL;
466     }
467     if (symbol == NULL) {
468 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null function name");
469 jds 103 return NULL;
470     }
471    
472     dlreturn = AscFindDLRecord(libname);
473     if (dlreturn == NULL) {
474 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested library %s", libname);
475 jds 103 return NULL;
476     }
477     #ifdef __hpux
478     i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
479     if (i == -1) {
480 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested function '%s' in %s (%s)",
481 jds 103 symbol, libname, strerror(errno));
482     symreturn = NULL;
483     }
484     #elif defined(__WIN32__)
485     /* no problem on Windows - GetProcAddress() returns a function pointer. */
486     symreturn = (DynamicF)GetProcAddress((HINSTANCE)dlreturn, symbol);
487     #else
488     /*
489     * Here's the corresponding bit of possibly-misdirected casting horror.
490     * ISO C forbids casting between function and data pointers, so, naturally,
491 johnpye 190 * we cast between function and data pointers. Well, we don't have much
492 jds 103 * choice. dlsym() returns a void* for both variables and functions so we
493 johnpye 190 * have to do the cast for functions. This is ok on POSIX systems since the
494     * pointer types are compatible. Then, to avoid being reminded by the
495     * compiler that we're doing something illegal, we apply convoluted casting
496 jds 103 * to shut it up. Oh, the crap you can find on the internet... JDS
497     */
498     *(void**)(&symreturn) = dlsym(dlreturn, symbol);
499     #endif
500     if (symreturn == NULL) {
501 johnpye 790 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested function '%s' in %s",symbol,libname);
502     ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type: %s",ASC_DLERRSTRING);
503 jds 103 }
504     return symreturn;
505     }
506 johnpye 427
507 johnpye 791
508     /*-----------------------------------------------------------------------------
509     SEARCHING FOR LIBRARIES
510     */
511    
512 jpye 1597
513 johnpye 791 /**
514 jpye 1597 Create a library filename according to platform standard naming.
515    
516     @param partialname The partial filename (eg 'mylib')
517     @return Complete filename (eg 'libmylib.so' or 'mylib.dlll', etc)
518    
519     Basically just adds ASC_SHLIBPREFIX to start and ASC_SHLIBSUFFIX to end.
520    
521     No allowance made for 'soname' suffixes eg 'libsomething.so.1' etc. But
522     that's probably OK as those methods aren't really applicable to dlopened
523     libraries (eg the soname symlink mechanism breaks down).
524     */
525     char *dynaload_lib_filename(const char *partialname){
526     char *buffer;
527     buffer = ASC_NEW_ARRAY(char,PATH_MAX);
528     #if !defined(ASC_SHLIBSUFFIX) || !defined(ASC_SHLIBPREFIX)
529     # error "ASC_SHLIBSUFFIX and ASC_SHLIBPREFIX are not defined"
530     #endif
531     snprintf(buffer,PATH_MAX,"%s%s%s",ASC_SHLIBPREFIX,partialname,ASC_SHLIBSUFFIX);
532     return buffer;
533     }
534    
535    
536     /**
537 johnpye 791 A little structure to help with searching for libraries
538    
539     @see test_librarysearch
540     */
541     struct LibrarySearch{
542     struct FilePath *partialpath;
543     char fullpath[PATH_MAX];
544     };
545    
546     FilePathTestFn test_librarysearch;
547    
548     /**
549     A 'test' function for passing to the ospath_searchpath_iterate function.
550     This test function will return a match when a library having the required
551     name is present in the fully resolved path.
552     */
553     int test_librarysearch(struct FilePath *path, void *userdata){
554     /* user data = the relative path, plus a place
555     to store the full path when found */
556     FILE *f;
557     struct LibrarySearch *ls;
558     struct FilePath *fp;
559    
560     ls = (struct LibrarySearch *)userdata;
561     fp = ospath_concat(path,ls->partialpath);
562     if(fp==NULL){
563     char *tmp;
564     tmp = ospath_str(path);
565     CONSOLE_DEBUG("Unable to concatenate '%s'...",tmp);
566     ospath_free_str(tmp);
567     tmp = ospath_str(ls->partialpath);
568     CONSOLE_DEBUG("... and '%s'...",tmp);
569     ospath_free_str(tmp);
570     return 0;
571     }
572    
573     ospath_strncpy(fp,ls->fullpath,PATH_MAX);
574 johnpye 895 /* CONSOLE_DEBUG("SEARCHING FOR %s",ls->fullpath); */
575 johnpye 791
576     f = ospath_fopen(fp,"r");
577     if(f==NULL){
578     ospath_free(fp);
579     return 0;
580     }
581     fclose(f);
582    
583     /* ERROR_REPORTER_HERE(ASC_PROG_NOTE,"FOUND! %s\n",ls->fullpath); */
584     ospath_free(fp);
585     return 1;
586     }
587    
588 johnpye 862 /**
589     @DEPRECATED this function needs to be rewritten to use 'ImportHandler'
590     functionality.
591     */
592 johnpye 1072 char *SearchArchiveLibraryPath(CONST char *name, char *dpath, const char *envv){
593 johnpye 791 struct FilePath *fp1, *fp2, *fp3; /* relative path */
594     char *s1;
595 johnpye 862 char *buffer;
596 johnpye 791
597     struct LibrarySearch ls;
598     struct FilePath **sp;
599     char *path, *foundpath;
600     ospath_stat_t buf;
601     FILE *f;
602    
603     fp1 = ospath_new_noclean(name);
604     if(fp1==NULL){
605     ERROR_REPORTER_HERE(ASC_USER_ERROR,"Invalid partial path '%s'",name);
606     ospath_free(fp1);
607     return NULL;
608     }
609    
610     s1 = ospath_getfilestem(fp1);
611     if(s1==NULL){
612     /* not a file, so fail... */
613     return NULL;
614     }
615    
616     fp2 = ospath_getdir(fp1);
617     if(fp2==NULL){
618     ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to retrieve file dir");
619     return NULL;
620     }
621    
622 jpye 1597 buffer = dynaload_lib_filename(s1);
623 johnpye 791
624     fp3 = ospath_new(buffer);
625 johnpye 862 ASC_FREE(buffer);
626 johnpye 791 ospath_free(fp1);
627     fp1 = ospath_concat(fp2,fp3);
628     ospath_free(fp2);
629     ospath_free(fp3);
630     ospath_free_str(s1);
631    
632     /* attempt to open "name" directly */
633     if(0==ospath_stat(fp1,&buf) && NULL!=(f = ospath_fopen(fp1,"r")) ){
634     char *tmp;
635     tmp = ospath_str(fp1);
636     CONSOLE_DEBUG("Library '%s' opened directly, without path search",tmp);
637     ospath_free_str(tmp);
638     fp2 = ospath_getabs(fp1);
639     foundpath = ospath_str(fp2);
640     ospath_free(fp2);
641     fclose(f);
642     }else{
643    
644     ls.partialpath = fp1;
645    
646     path=Asc_GetEnv(envv);
647     if(path==NULL){
648 johnpye 895 /* CONSOLE_DEBUG("Library search path env var '%s' not found, using default path '%s'",envv,dpath); */
649 johnpye 791 path=dpath;
650     }
651    
652     /* CONSOLE_DEBUG("SEARCHPATH IS %s",path); */
653     sp = ospath_searchpath_new(path);
654    
655     if(NULL==ospath_searchpath_iterate(sp,&test_librarysearch,&ls)){
656     ospath_free(fp1);
657     ospath_searchpath_free(sp);
658     return NULL;
659     }
660    
661     foundpath = ASC_NEW_ARRAY(char,strlen(ls.fullpath)+1);
662     strcpy(foundpath,ls.fullpath);
663     ospath_searchpath_free(sp);
664     }
665    
666     ospath_free(fp1);
667     return foundpath;
668     }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22