/src/netcdf-c/libncpoco/cp_unix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************* |
2 | | * Copyright 1993, UCAR/Unidata |
3 | | * See netcdf/COPYRIGHT file for copying and redistribution conditions. |
4 | | * Derived from poco library from Boost Software: see nccpoco/LICENSE file. |
5 | | *********************************************************************/ |
6 | | |
7 | | #include "config.h" |
8 | | #include <stdlib.h> |
9 | | #include <stdio.h> |
10 | | #include <string.h> |
11 | | #ifdef HAVE_DLFCN_H |
12 | | #include <dlfcn.h> |
13 | | #endif |
14 | | #ifdef USE_MUTEX |
15 | | #include <pthread.h> |
16 | | #endif |
17 | | |
18 | | #include "netcdf.h" |
19 | | #include "ncpoco.h" |
20 | | #include "ncpathmgr.h" |
21 | | |
22 | | #undef DEBUG |
23 | | |
24 | | /* Note: cygwin is missing RTLD_LOCAL, set it to 0 */ |
25 | | #if !defined(RTLD_LOCAL) |
26 | | #define RTLD_LOCAL 0 |
27 | | #endif |
28 | | |
29 | | #if !defined(RTLD_GLOBAL) |
30 | | #define RTLD_GLOBAL 0 |
31 | | #endif |
32 | | |
33 | | #if !defined(RTLD_LAZY) |
34 | | #define RTLD_LAZY 1 |
35 | | #endif |
36 | | |
37 | | #if !defined(RTLD_NOW) |
38 | | #define RTLD_NOW 2 |
39 | | #endif |
40 | | |
41 | | #ifdef USE_MUTEX |
42 | | static pthread_mutex_t mutex; |
43 | | #endif |
44 | | |
45 | | static void |
46 | | ncperr(const char* fcn, NCPSharedLib* lib) |
47 | 0 | { |
48 | 0 | const char* msg = dlerror(); |
49 | 0 | lib->err.msg[0] = '\0'; |
50 | 0 | if(msg != NULL) { |
51 | 0 | strlcat(lib->err.msg,fcn,sizeof(lib->err.msg)); |
52 | 0 | strlcat(lib->err.msg,": ",sizeof(lib->err.msg)); |
53 | 0 | strlcat(lib->err.msg,msg,sizeof(lib->err.msg)); |
54 | | #ifdef DEBUG |
55 | | fprintf(stderr,">>> %s\n",lib->err.msg); |
56 | | #endif |
57 | 0 | } |
58 | 0 | } |
59 | | |
60 | | int |
61 | | ncp_unix_initialize(void) |
62 | 0 | { |
63 | 0 | int ret = 1; |
64 | | #ifdef USE_MUTEX |
65 | | pthread_mutexattr_t attr; |
66 | | pthread_mutexattr_init(&attr); |
67 | | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); |
68 | | if(pthread_mutex_init(&mutex, &attr)) { |
69 | | fprintf(stderr,"cp_unix: Cannot create mutext\n"); |
70 | | ret = 1; |
71 | | } |
72 | | pthread_mutexattr_destroy(&attr); |
73 | | #endif |
74 | 0 | return ret; |
75 | 0 | } |
76 | | |
77 | | int |
78 | | ncp_unix_finalize(void) |
79 | 0 | { |
80 | | #ifdef USE_MUTEX |
81 | | pthread_mutex_destroy(&mutex); |
82 | | #endif |
83 | 0 | return 1; |
84 | 0 | } |
85 | | |
86 | | /**************************************************/ |
87 | | |
88 | | #ifdef USE_MUTEX |
89 | | static void lock(void) {pthread_mutex_lock(&mutex);} |
90 | | #else |
91 | | #define lock() |
92 | | #endif |
93 | | |
94 | | #ifdef USE_MUTEX |
95 | | static void unlock(void) {pthread_mutex_unlock(&mutex);} |
96 | | #else |
97 | | #define unlock() |
98 | | #endif |
99 | | |
100 | | /**************************************************/ |
101 | | |
102 | | static int |
103 | | init(NCPSharedLib* lib) |
104 | 0 | { |
105 | 0 | int ret = NC_NOERR; |
106 | 0 | return ret; |
107 | 0 | } |
108 | | |
109 | | static int |
110 | | reclaim(NCPSharedLib* lib) |
111 | 0 | { |
112 | 0 | int ret = NC_NOERR; |
113 | 0 | return ret; |
114 | 0 | } |
115 | | |
116 | | static int |
117 | | load(NCPSharedLib* lib , const char* path0, int flags) |
118 | 0 | { |
119 | 0 | int ret = NC_NOERR; |
120 | 0 | int realflags = RTLD_LAZY; /* versus RTLD_NOW which does not appear to work */ |
121 | 0 | char* path = NULL; |
122 | |
|
123 | 0 | if((path = NCpathcvt(path0))==NULL) {ret = NC_ENOMEM; goto done;} |
124 | | |
125 | 0 | lock(); |
126 | 0 | if(lib->state.handle != NULL) |
127 | 0 | {ret = NC_EEXIST; goto ldone;} |
128 | 0 | lib->path = nulldup(path); |
129 | 0 | lib->flags = flags; |
130 | 0 | if(flags & NCP_LOCAL) |
131 | 0 | realflags |= RTLD_LOCAL; |
132 | 0 | else |
133 | 0 | realflags |= RTLD_GLOBAL; |
134 | 0 | lib->state.flags = realflags; |
135 | 0 | lib->state.handle = dlopen(lib->path, lib->state.flags); |
136 | 0 | if(lib->state.handle == NULL) { |
137 | 0 | ncperr("dlopen",lib); |
138 | 0 | ret = NC_ENOTFOUND; |
139 | 0 | goto ldone; |
140 | 0 | } |
141 | 0 | ldone: |
142 | 0 | unlock(); |
143 | 0 | done: |
144 | 0 | nullfree(path); |
145 | 0 | return ret; |
146 | 0 | } |
147 | | |
148 | | static int |
149 | | unload(NCPSharedLib* lib) |
150 | 0 | { |
151 | 0 | int ret = NC_NOERR; |
152 | 0 | lock(); |
153 | 0 | if(lib->state.handle != NULL) { |
154 | 0 | dlclose(lib->state.handle); |
155 | 0 | lib->state.handle = NULL; |
156 | 0 | } |
157 | 0 | unlock(); |
158 | 0 | return ret; |
159 | 0 | } |
160 | | |
161 | | static int |
162 | | isLoaded(NCPSharedLib* lib) |
163 | 0 | { |
164 | 0 | return lib->state.handle != NULL; |
165 | 0 | } |
166 | | |
167 | | static void* |
168 | | getsymbol(NCPSharedLib* lib, const char* name) |
169 | 0 | { |
170 | 0 | void* result = NULL; |
171 | 0 | lock(); |
172 | 0 | if(lib->state.handle != NULL) { |
173 | 0 | result = dlsym(lib->state.handle, name); |
174 | 0 | if(result == NULL) { |
175 | 0 | ncperr("dlsym",lib); |
176 | 0 | } |
177 | 0 | } |
178 | 0 | unlock(); |
179 | 0 | return result; |
180 | 0 | } |
181 | | |
182 | | static const char* |
183 | | getpath(NCPSharedLib* lib) |
184 | 0 | { |
185 | 0 | return lib->path; |
186 | 0 | } |
187 | | |
188 | | struct NCPAPI ncp_unix_api = { |
189 | | init, |
190 | | reclaim, |
191 | | load, |
192 | | unload, |
193 | | isLoaded, |
194 | | getsymbol, |
195 | | getpath, |
196 | | }; |