1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <ctype.h>
6
7 #include "cdf.h"
8 #include "cdi.h"
9 #include "cdi_int.h"
10 #include "cdf_int.h"
11
12
cdfLibraryVersion(void)13 const char *cdfLibraryVersion(void)
14 {
15 #ifdef HAVE_LIBNETCDF
16 return nc_inq_libvers();
17 #else
18 return "library undefined";
19 #endif
20 }
21
22 #ifdef HAVE_H5GET_LIBVERSION
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 int H5get_libversion(unsigned *, unsigned *, unsigned *);
27 #ifdef __cplusplus
28 }
29 #endif
30 #endif
31
hdfLibraryVersion(void)32 const char *hdfLibraryVersion(void)
33 {
34 #ifdef HAVE_H5GET_LIBVERSION
35 static char hdf_libvers[256];
36 static int linit = 0;
37 if (!linit)
38 {
39 linit = 1;
40 unsigned majnum, minnum, relnum;
41 H5get_libversion(&majnum, &minnum, &relnum);
42 #ifdef HAVE_NC4HDF5_THREADSAFE
43 sprintf(hdf_libvers, "%u.%u.%u threadsafe", majnum, minnum, relnum);
44 #else
45 sprintf(hdf_libvers, "%u.%u.%u", majnum, minnum, relnum);
46 #endif
47 }
48
49 return hdf_libvers;
50 #else
51 return "library undefined";
52 #endif
53 }
54
55
56 int CDF_Debug = 0; /* If set to 1, debugging */
57
58
cdfDebug(int debug)59 void cdfDebug(int debug)
60 {
61 CDF_Debug = debug;
62
63 if ( CDF_Debug )
64 Message("debug level %d", debug);
65 }
66
67 #ifdef HAVE_LIBNETCDF
68 static
cdfComment(int ncid)69 void cdfComment(int ncid)
70 {
71 static char comment[256] = "Climate Data Interface version ";
72 static bool init = false;
73
74 if ( ! init )
75 {
76 init = true;
77 const char *libvers = cdiLibraryVersion();
78
79 if ( ! isdigit((int) *libvers) )
80 strcat(comment, "??");
81 else
82 strcat(comment, libvers);
83 strcat(comment, " (https://mpimet.mpg.de/cdi)");
84 }
85
86 cdf_put_att_text(ncid, NC_GLOBAL, "CDI", strlen(comment), comment);
87 }
88 #endif
89
cdfOpenFile(const char * filename,const char * mode,int * filetype)90 static int cdfOpenFile(const char *filename, const char *mode, int *filetype)
91 {
92 int ncid = -1;
93 #ifdef HAVE_LIBNETCDF
94 int fmode = tolower(*mode);
95 int writemode = NC_CLOBBER;
96 int readmode = NC_NOWRITE;
97
98 if ( filename == NULL )
99 ncid = CDI_EINVAL;
100 else
101 {
102 switch (fmode)
103 {
104 case 'r':
105 {
106 const int status = cdf_open(filename, readmode, &ncid);
107 if ( status > 0 && ncid < 0 ) ncid = CDI_ESYSTEM;
108 #ifdef HAVE_NETCDF4
109 else
110 {
111 int format;
112 (void) nc_inq_format(ncid, &format);
113 if ( format == NC_FORMAT_NETCDF4_CLASSIC )
114 *filetype = CDI_FILETYPE_NC4C;
115 }
116 #endif
117 }
118 break;
119 case 'w':
120 #ifdef NC_64BIT_OFFSET
121 if ( *filetype == CDI_FILETYPE_NC2 ) writemode |= NC_64BIT_OFFSET;
122 #endif
123 #ifdef NC_64BIT_DATA
124 if ( *filetype == CDI_FILETYPE_NC5 ) writemode |= NC_64BIT_DATA;
125 #endif
126 #ifdef HAVE_NETCDF4
127 if ( *filetype == CDI_FILETYPE_NC4 ) writemode |= NC_NETCDF4;
128 else if ( *filetype == CDI_FILETYPE_NC4C ) writemode |= NC_NETCDF4 | NC_CLASSIC_MODEL;
129 #endif
130 cdf_create(filename, writemode, &ncid);
131 if (CDI_Version_Info) cdfComment(ncid);
132 cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.6");
133 break;
134 case 'a':
135 cdf_open(filename, NC_WRITE, &ncid);
136 break;
137 default:
138 ncid = CDI_EINVAL;
139 }
140 }
141 #endif
142
143 return ncid;
144 }
145
146
cdfOpen(const char * filename,const char * mode,int filetype)147 int cdfOpen(const char *filename, const char *mode, int filetype)
148 {
149 int fileID = -1;
150 bool open_file = true;
151
152 if ( CDF_Debug )
153 Message("Open %s with mode %c", filename, *mode);
154
155 #ifdef HAVE_LIBNETCDF
156 #ifndef NC_64BIT_OFFSET
157 if ( filetype == CDI_FILETYPE_NC2 ) open_file = false;
158 #endif
159 #ifndef NC_64BIT_DATA
160 if ( filetype == CDI_FILETYPE_NC5 ) open_file = false;
161 #endif
162 #endif
163
164 if ( open_file )
165 {
166 fileID = cdfOpenFile(filename, mode, &filetype);
167
168 if ( CDF_Debug )
169 Message("File %s opened with id %d", filename, fileID);
170 }
171 else
172 {
173 fileID = CDI_ELIBNAVAIL;
174 }
175
176 return fileID;
177 }
178
179 static
cdf4CheckLibVersions(void)180 int cdf4CheckLibVersions(void)
181 {
182 int status = 0;
183 #ifdef HAVE_NETCDF4
184 #ifdef HAVE_H5GET_LIBVERSION
185 static int checked = 0;
186 if (!checked)
187 {
188 checked = 1;
189 unsigned majnum, minnum, relnum;
190
191 sscanf(nc_inq_libvers(), "%u.%u.%u", &majnum, &minnum, &relnum);
192 //printf("netCDF %u.%u.%u\n", majnum, minnum, relnum);
193 const unsigned ncmaxver = 4 * 1000000 + 4 * 1000;
194 const unsigned nclibver = majnum * 1000000 + minnum * 1000 + relnum;
195
196 if (nclibver <= ncmaxver)
197 {
198 H5get_libversion(&majnum, &minnum, &relnum);
199 const unsigned hdf5maxver = 1 * 1000000 + 10 * 1000;
200 const unsigned hdf5libver = majnum * 1000000 + minnum * 1000 + relnum;
201
202 if (hdf5libver >= hdf5maxver)
203 {
204 fprintf(stderr, "NetCDF library 4.4.0 or earlier, combined with libhdf5 1.10.0 or greater not supported!\n");
205 status = 1;
206 }
207 }
208 }
209 #endif
210 #endif
211 return status;
212 }
213
cdf4Open(const char * filename,const char * mode,int * filetype)214 int cdf4Open(const char *filename, const char *mode, int *filetype)
215 {
216 int fileID = -1;
217 bool open_file = false;
218
219 if ( CDF_Debug ) Message("Open %s with mode %c", filename, *mode);
220
221 #ifdef HAVE_NETCDF4
222 open_file = true;
223 #endif
224
225 if ( open_file )
226 {
227 if (cdf4CheckLibVersions() == 0)
228 {
229 fileID = cdfOpenFile(filename, mode, filetype);
230 if ( CDF_Debug ) Message("File %s opened with id %d", filename, fileID);
231 }
232 else
233 {
234 fileID = CDI_EUFTYPE;
235 }
236 }
237 else
238 {
239 fileID = CDI_ELIBNAVAIL;
240 }
241
242 return fileID;
243 }
244
245
cdfCloseFile(int fileID)246 static void cdfCloseFile(int fileID)
247 {
248 #ifdef HAVE_LIBNETCDF
249 cdf_close(fileID);
250 #endif
251 }
252
cdfClose(int fileID)253 void cdfClose(int fileID)
254 {
255 cdfCloseFile(fileID);
256 }
257 /*
258 * Local Variables:
259 * c-file-style: "Java"
260 * c-basic-offset: 2
261 * indent-tabs-mode: nil
262 * show-trailing-whitespace: t
263 * require-trailing-newline: t
264 * End:
265 */
266