NetCDF  4.6.2
dfile.c
Go to the documentation of this file.
1 
13 #include "config.h"
14 #include <stdlib.h>
15 #ifdef HAVE_SYS_RESOURCE_H
16 #include <sys/resource.h>
17 #endif
18 #ifdef HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 #ifdef HAVE_SYS_STAT_H
22 #include <sys/stat.h>
23 #endif
24 
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h> /* lseek() */
27 #endif
28 
29 #include "ncdispatch.h"
30 #include "netcdf_mem.h"
31 #include "ncwinpath.h"
32 #include "fbits.h"
33 
34 /* If Defined, then use only stdio for all magic number io;
35  otherwise use stdio or mpio as required.
36  */
37 #undef DEBUG
38 
43 struct MagicFile {
44  const char* path;
45  long long filelen;
46  int use_parallel;
47  int inmemory;
48  int diskless;
49  void* parameters; /* !NULL if inmemory && !diskless */
50  FILE* fp;
51 #ifdef USE_PARALLEL
52  MPI_File fh;
53 #endif
54 };
55 
56 static int openmagic(struct MagicFile* file);
57 static int readmagic(struct MagicFile* file, long pos, char* magic);
58 static int closemagic(struct MagicFile* file);
59 #ifdef DEBUG
60 static void printmagic(const char* tag, char* magic,struct MagicFile*);
61 #endif
62 
63 extern int NC_initialized;
67 static char HDF5_SIGNATURE[MAGIC_NUMBER_LEN] = "\211HDF\r\n\032\n";
68 
69 #ifdef USE_NETCDF4
70 /* User-defined formats. */
71 NC_Dispatch *UDF0_dispatch_table = NULL;
72 char UDF0_magic_number[NC_MAX_MAGIC_NUMBER_LEN + 1] = "";
73 NC_Dispatch *UDF1_dispatch_table = NULL;
74 char UDF1_magic_number[NC_MAX_MAGIC_NUMBER_LEN + 1] = "";
75 #endif /* USE_NETCDF4 */
76 
113 #ifdef USE_NETCDF4
114 
127 int
128 nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number)
129 {
130  /* Check inputs. */
131  if (mode_flag != NC_UDF0 && mode_flag != NC_UDF1)
132  return NC_EINVAL;
133  if (!dispatch_table)
134  return NC_EINVAL;
135  if (magic_number && strlen(magic_number) > NC_MAX_MAGIC_NUMBER_LEN)
136  return NC_EINVAL;
137 
138  /* Retain a pointer to the dispatch_table and a copy of the magic
139  * number, if one was provided. */
140  switch(mode_flag)
141  {
142  case NC_UDF0:
143  UDF0_dispatch_table = dispatch_table;
144  if (magic_number)
145  strncpy(UDF0_magic_number, magic_number, NC_MAX_MAGIC_NUMBER_LEN);
146  break;
147  case NC_UDF1:
148  UDF1_dispatch_table = dispatch_table;
149  if (magic_number)
150  strncpy(UDF1_magic_number, magic_number, NC_MAX_MAGIC_NUMBER_LEN);
151  break;
152  }
153 
154  return NC_NOERR;
155 }
156 
173 int
174 nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
175 {
176  /* Check inputs. */
177  if (mode_flag != NC_UDF0 && mode_flag != NC_UDF1)
178  return NC_EINVAL;
179 
180  switch(mode_flag)
181  {
182  case NC_UDF0:
183  if (dispatch_table)
184  *dispatch_table = UDF0_dispatch_table;
185  if (magic_number)
186  strncpy(magic_number, UDF0_magic_number, NC_MAX_MAGIC_NUMBER_LEN);
187  break;
188  case NC_UDF1:
189  if (dispatch_table)
190  *dispatch_table = UDF1_dispatch_table;
191  if (magic_number)
192  strncpy(magic_number, UDF1_magic_number, NC_MAX_MAGIC_NUMBER_LEN);
193  break;
194  }
195 
196  return NC_NOERR;
197 }
198 #endif /* USE_NETCDF4 */
199 
214 static int
215 NC_interpret_magic_number(char* magic, int* model, int* version)
216 {
217  int status = NC_NOERR;
218  /* Look at the magic number */
219  *model = 0;
220  *version = 0;
221 #ifdef USE_NETCDF4
222  if (strlen(UDF0_magic_number) && !strncmp(UDF0_magic_number, magic,
223  strlen(UDF0_magic_number)))
224  {
225  *model = NC_FORMATX_UDF0;
226  *version = 6; /* redundant */
227  goto done;
228  }
229  if (strlen(UDF1_magic_number) && !strncmp(UDF1_magic_number, magic,
230  strlen(UDF1_magic_number)))
231  {
232  *model = NC_FORMATX_UDF1;
233  *version = 7; /* redundant */
234  goto done;
235  }
236 #endif /* USE_NETCDF4 */
237 
238  /* Use the complete magic number string for HDF5 */
239  if(memcmp(magic,HDF5_SIGNATURE,sizeof(HDF5_SIGNATURE))==0) {
240  *model = NC_FORMATX_NC4;
241  *version = 5; /* redundant */
242  goto done;
243  }
244  if(magic[0] == '\016' && magic[1] == '\003'
245  && magic[2] == '\023' && magic[3] == '\001') {
246  *model = NC_FORMATX_NC_HDF4;
247  *version = 4; /* redundant */
248  goto done;
249  }
250  if(magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F') {
251  if(magic[3] == '\001') {
252  *version = 1; /* netcdf classic version 1 */
253  *model = NC_FORMATX_NC3;
254  goto done;
255  }
256  if(magic[3] == '\002') {
257  *version = 2; /* netcdf classic version 2 */
258  *model = NC_FORMATX_NC3;
259  goto done;
260  }
261  if(magic[3] == '\005') {
262  *version = 5; /* cdf5 file */
263  *model = NC_FORMATX_NC3;
264  goto done;
265  }
266  }
267  /* No match */
268  status = NC_ENOTNC;
269  goto done;
270 
271 done:
272  return status;
273 }
274 
290 static int
291 NC_check_file_type(const char *path, int flags, int use_parallel,
292  void *parameters, int* model, int* version)
293 {
294  char magic[MAGIC_NUMBER_LEN];
295  int status = NC_NOERR;
296  int diskless = ((flags & NC_DISKLESS) == NC_DISKLESS);
297  int inmemory = ((flags & NC_INMEMORY) == NC_INMEMORY);
298  int mmap = ((flags & NC_MMAP) == NC_MMAP);
299 
300  struct MagicFile file;
301 
302  *model = 0;
303  *version = 0;
304 
305  /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
306  if(diskless && inmemory) {status = NC_EDISKLESS; goto done;}
307  if(diskless && mmap) {status = NC_EDISKLESS; goto done;}
308  if(inmemory && mmap) {status = NC_EINMEMORY; goto done;}
309 
310  /* mmap is not allowed for netcdf-4 */
311  if(mmap && (flags & NC_NETCDF4)) {status = NC_EINVAL; goto done;}
312 
313  memset((void*)&file,0,sizeof(file));
314  file.path = path; /* do not free */
315  file.parameters = parameters;
316  file.inmemory = inmemory;
317  file.diskless = diskless;
318  file.use_parallel = use_parallel;
319 
320  status = openmagic(&file);
321  if(status != NC_NOERR) {goto done;}
322  /* Verify we have a large enough file */
323  if(file.filelen < MAGIC_NUMBER_LEN)
324  {status = NC_ENOTNC; goto done;}
325  if((status = readmagic(&file,0L,magic)) != NC_NOERR) {
326  status = NC_ENOTNC;
327  *model = 0;
328  *version = 0;
329  goto done;
330  }
331  /* Look at the magic number */
332  if(NC_interpret_magic_number(magic,model,version) == NC_NOERR
333  && *model != 0) {
334  if (*model == NC_FORMATX_NC3 && use_parallel)
335  /* this is called from nc_open_par() and file is classic */
336  *model = NC_FORMATX_PNETCDF;
337  goto done; /* found something */
338  }
339 
340  /* Remaining case is to search forward at starting at 512
341  and doubling to see if we have HDF5 magic number */
342  {
343  long pos = 512L;
344  for(;;) {
345  if((pos+MAGIC_NUMBER_LEN) > file.filelen)
346  {status = NC_ENOTNC; goto done;}
347  if((status = readmagic(&file,pos,magic)) != NC_NOERR)
348  {status = NC_ENOTNC; goto done; }
349  NC_interpret_magic_number(magic,model,version);
350  if(*model == NC_FORMATX_NC4) break;
351  /* double and try again */
352  pos = 2*pos;
353  }
354  }
355 done:
356  closemagic(&file);
357  return status;
358 }
359 
553 int
554 nc_create(const char *path, int cmode, int *ncidp)
555 {
556  return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
557 }
558 
625 int
626 nc__create(const char *path, int cmode, size_t initialsz,
627  size_t *chunksizehintp, int *ncidp)
628 {
629  return NC_create(path, cmode, initialsz, 0,
630  chunksizehintp, 0, NULL, ncidp);
631 }
632 
671 int
672 nc_create_mem(const char* path, int mode, size_t initialsize, int* ncidp)
673 {
674  if(mode & NC_MMAP) return NC_EINVAL;
675  mode |= NC_INMEMORY; /* Specifically, do not set NC_DISKLESS */
676  return NC_create(path, mode, initialsize, 0, NULL, 0, NULL, ncidp);
677 }
678 
698 int
699 nc__create_mp(const char *path, int cmode, size_t initialsz,
700  int basepe, size_t *chunksizehintp, int *ncidp)
701 {
702  return NC_create(path, cmode, initialsz, basepe,
703  chunksizehintp, 0, NULL, ncidp);
704 }
705 
819 int
820 nc_open(const char *path, int omode, int *ncidp)
821 {
822  return NC_open(path, omode, 0, NULL, 0, NULL, ncidp);
823 }
824 
876 int
877 nc__open(const char *path, int omode,
878  size_t *chunksizehintp, int *ncidp)
879 {
880  /* this API is for non-parallel access.
881  * Note nc_open_par() also calls NC_open().
882  */
883  return NC_open(path, omode, 0, chunksizehintp, 0, NULL, ncidp);
884 }
885 
931 int
932 nc_open_mem(const char* path, int omode, size_t size, void* memory, int* ncidp)
933 {
934  NC_memio meminfo;
935 
936  /* Sanity checks */
937  if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL)
938  return NC_EINVAL;
939  if(omode & (NC_WRITE|NC_MMAP))
940  return NC_EINVAL;
941  omode |= (NC_INMEMORY); /* Note: NC_INMEMORY and NC_DISKLESS are mutually exclusive*/
942  meminfo.size = size;
943  meminfo.memory = memory;
944  meminfo.flags = NC_MEMIO_LOCKED;
945  return NC_open(path, omode, 0, NULL, 0, &meminfo, ncidp);
946 }
947 
996 int
997 nc_open_memio(const char* path, int omode, NC_memio* params, int* ncidp)
998 {
999  /* Sanity checks */
1000  if(path == NULL || params == NULL)
1001  return NC_EINVAL;
1002  if(params->memory == NULL || params->size < MAGIC_NUMBER_LEN)
1003  return NC_EINVAL;
1004 
1005  if(omode & NC_MMAP)
1006  return NC_EINVAL;
1007  omode |= (NC_INMEMORY);
1008  return NC_open(path, omode, 0, NULL, 0, params, ncidp);
1009 }
1010 
1029 int
1030 nc__open_mp(const char *path, int omode, int basepe,
1031  size_t *chunksizehintp, int *ncidp)
1032 {
1033  return NC_open(path, omode, basepe, chunksizehintp, 0, NULL, ncidp);
1034 }
1035 
1053 int
1054 nc_inq_path(int ncid, size_t *pathlen, char *path)
1055 {
1056  NC* ncp;
1057  int stat = NC_NOERR;
1058  if ((stat = NC_check_id(ncid, &ncp)))
1059  return stat;
1060  if(ncp->path == NULL) {
1061  if(pathlen) *pathlen = 0;
1062  if(path) path[0] = '\0';
1063  } else {
1064  if (pathlen) *pathlen = strlen(ncp->path);
1065  if (path) strcpy(path, ncp->path);
1066  }
1067  return stat;
1068 }
1069 
1118 int
1119 nc_redef(int ncid)
1120 {
1121  NC* ncp;
1122  int stat = NC_check_id(ncid, &ncp);
1123  if(stat != NC_NOERR) return stat;
1124  return ncp->dispatch->redef(ncid);
1125 }
1126 
1182 int
1183 nc_enddef(int ncid)
1184 {
1185  int status = NC_NOERR;
1186  NC *ncp;
1187  status = NC_check_id(ncid, &ncp);
1188  if(status != NC_NOERR) return status;
1189  return ncp->dispatch->_enddef(ncid,0,1,0,1);
1190 }
1191 
1273 int
1274 nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree,
1275  size_t r_align)
1276 {
1277  NC* ncp;
1278  int stat = NC_check_id(ncid, &ncp);
1279  if(stat != NC_NOERR) return stat;
1280  return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
1281 }
1282 
1350 int
1351 nc_sync(int ncid)
1352 {
1353  NC* ncp;
1354  int stat = NC_check_id(ncid, &ncp);
1355  if(stat != NC_NOERR) return stat;
1356  return ncp->dispatch->sync(ncid);
1357 }
1358 
1402 int
1403 nc_abort(int ncid)
1404 {
1405  NC* ncp;
1406  int stat = NC_check_id(ncid, &ncp);
1407  if(stat != NC_NOERR) return stat;
1408 
1409 #ifdef USE_REFCOUNT
1410  /* What to do if refcount > 0? */
1411  /* currently, forcibly abort */
1412  ncp->refcount = 0;
1413 #endif
1414 
1415  stat = ncp->dispatch->abort(ncid);
1416  del_from_NCList(ncp);
1417  free_NC(ncp);
1418  return stat;
1419 }
1420 
1461 int
1462 nc_close(int ncid)
1463 {
1464  NC* ncp;
1465  int stat = NC_check_id(ncid, &ncp);
1466  if(stat != NC_NOERR) return stat;
1467 
1468 #ifdef USE_REFCOUNT
1469  ncp->refcount--;
1470  if(ncp->refcount <= 0)
1471 #endif
1472  {
1473  stat = ncp->dispatch->close(ncid,NULL);
1474  /* Remove from the nc list */
1475  if (!stat)
1476  {
1477  del_from_NCList(ncp);
1478  free_NC(ncp);
1479  }
1480  }
1481  return stat;
1482 }
1483 
1526 int
1527 nc_close_memio(int ncid, NC_memio* memio)
1528 {
1529  NC* ncp;
1530  int stat = NC_check_id(ncid, &ncp);
1531  if(stat != NC_NOERR) return stat;
1532 
1533 #ifdef USE_REFCOUNT
1534  ncp->refcount--;
1535  if(ncp->refcount <= 0)
1536 #endif
1537  {
1538  stat = ncp->dispatch->close(ncid,memio);
1539  /* Remove from the nc list */
1540  if (!stat)
1541  {
1542  del_from_NCList(ncp);
1543  free_NC(ncp);
1544  }
1545  }
1546  return stat;
1547 }
1548 
1647 int
1648 nc_set_fill(int ncid, int fillmode, int *old_modep)
1649 {
1650  NC* ncp;
1651  int stat = NC_check_id(ncid, &ncp);
1652  if(stat != NC_NOERR) return stat;
1653  return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1654 }
1655 
1670 int
1671 nc_inq_base_pe(int ncid, int *pe)
1672 {
1673  NC* ncp;
1674  int stat = NC_check_id(ncid, &ncp);
1675  if(stat != NC_NOERR) return stat;
1676  return ncp->dispatch->inq_base_pe(ncid,pe);
1677 }
1678 
1693 int
1694 nc_set_base_pe(int ncid, int pe)
1695 {
1696  NC* ncp;
1697  int stat = NC_check_id(ncid, &ncp);
1698  if(stat != NC_NOERR) return stat;
1699  return ncp->dispatch->set_base_pe(ncid,pe);
1700 }
1701 
1720 int
1721 nc_inq_format(int ncid, int *formatp)
1722 {
1723  NC* ncp;
1724  int stat = NC_check_id(ncid, &ncp);
1725  if(stat != NC_NOERR) return stat;
1726  return ncp->dispatch->inq_format(ncid,formatp);
1727 }
1728 
1755 int
1756 nc_inq_format_extended(int ncid, int *formatp, int *modep)
1757 {
1758  NC* ncp;
1759  int stat = NC_check_id(ncid, &ncp);
1760  if(stat != NC_NOERR) return stat;
1761  return ncp->dispatch->inq_format_extended(ncid,formatp,modep);
1762 }
1763 
1808 int
1809 nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1810 {
1811  NC* ncp;
1812  int stat = NC_check_id(ncid, &ncp);
1813  if(stat != NC_NOERR) return stat;
1814  return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1815 }
1816 
1827 int
1828 nc_inq_nvars(int ncid, int *nvarsp)
1829 {
1830  NC* ncp;
1831  int stat = NC_check_id(ncid, &ncp);
1832  if(stat != NC_NOERR) return stat;
1833  return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1834 }
1835 
1901 int
1902 nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1903 {
1904  NC* ncp;
1905  int stat;
1906 
1907  /* Do a quick triage on xtype */
1908  if(xtype <= NC_NAT) return NC_EBADTYPE;
1909  /* For compatibility, we need to allow inq about
1910  atomic types, even if ncid is ill-defined */
1911  if(xtype <= ATOMICTYPEMAX4) {
1912  if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1913  if(size) *size = NC_atomictypelen(xtype);
1914  return NC_NOERR;
1915  }
1916  /* Apparently asking about a user defined type, so we need
1917  a valid ncid */
1918  stat = NC_check_id(ncid, &ncp);
1919  if(stat != NC_NOERR) /* bad ncid */
1920  return NC_EBADTYPE;
1921  /* have good ncid */
1922  return ncp->dispatch->inq_type(ncid,xtype,name,size);
1923 }
1924 
1941 static int
1943 {
1944  int mode_format;
1945  int mmap = 0;
1946  int inmemory = 0;
1947  int diskless = 0;
1948 
1949  /* This is a clever check to see if more than one format bit is
1950  * set. */
1951  mode_format = (mode & NC_NETCDF4) | (mode & NC_64BIT_OFFSET) |
1952  (mode & NC_CDF5);
1953  if (mode_format && (mode_format & (mode_format - 1)))
1954  return NC_EINVAL;
1955 
1956  mmap = ((mode & NC_MMAP) == NC_MMAP);
1957  inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY);
1958  diskless = ((mode & NC_DISKLESS) == NC_DISKLESS);
1959 
1960  /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
1961  if(diskless && inmemory) return NC_EDISKLESS;
1962  if(diskless && mmap) return NC_EDISKLESS;
1963  if(inmemory && mmap) return NC_EINMEMORY;
1964 
1965  /* mmap is not allowed for netcdf-4 */
1966  if(mmap && (mode & NC_NETCDF4)) return NC_EINVAL;
1967 
1968  /* Can't use both parallel and diskless|inmemory|mmap. */
1969  if (mode & NC_MPIIO && mode & (NC_DISKLESS|NC_INMEMORY|NC_MMAP))
1970  return NC_EINVAL;
1971 
1972 #ifndef USE_NETCDF4
1973  /* If the user asks for a netCDF-4 file, and the library was built
1974  * without netCDF-4, then return an error.*/
1975  if (mode & NC_NETCDF4)
1976  return NC_ENOTBUILT;
1977 #endif /* USE_NETCDF4 undefined */
1978 
1979  /* Well I guess there is some sanity in the world after all. */
1980  return NC_NOERR;
1981 }
1982 
2010 int
2011 NC_create(const char *path0, int cmode, size_t initialsz,
2012  int basepe, size_t *chunksizehintp, int useparallel,
2013  void* parameters, int *ncidp)
2014 {
2015  int stat = NC_NOERR;
2016  NC* ncp = NULL;
2017  NC_Dispatch* dispatcher = NULL;
2018  /* Need three pieces of information for now */
2019  int model = NC_FORMATX_UNDEFINED; /* one of the NC_FORMATX values */
2020  int isurl = 0; /* dap or cdmremote or neither */
2021  char* path = NULL;
2022 
2023  TRACE(nc_create);
2024  if(path0 == NULL)
2025  return NC_EINVAL;
2026 
2027  /* Check mode flag for sanity. */
2028  if ((stat = check_create_mode(cmode)))
2029  return stat;
2030 
2031  /* Initialize the library. The available dispatch tables
2032  * will depend on how netCDF was built
2033  * (with/without netCDF-4, DAP, CDMREMOTE). */
2034  if(!NC_initialized)
2035  {
2036  if ((stat = nc_initialize()))
2037  return stat;
2038  }
2039 
2040 #ifdef WINPATH
2041  /* Need to do path conversion */
2042  path = NCpathcvt(path0);
2043 #else
2044  path = nulldup(path0);
2045 #endif
2046 
2047 #ifdef USE_REFCOUNT
2048  /* If this path is already open, then fail */
2049  ncp = find_in_NCList_by_name(path);
2050  if(ncp != NULL) {
2051  nullfree(path);
2052  return NC_ENFILE;
2053  }
2054 #endif
2055 
2056  {
2057  char* newpath = NULL;
2058  model = NC_urlmodel(path,cmode,&newpath);
2059  isurl = (model != 0);
2060  if(isurl) {
2061  nullfree(path);
2062  path = newpath;
2063  }
2064  }
2065 
2066  /* determine the model */
2067 #ifdef USE_NETCDF4
2068  if (model == NC_FORMATX_UNDEFINED && (cmode & NC_NETCDF4))
2069  model = NC_FORMATX_NC4;
2070 #else
2071  if (model == NC_FORMATX_UNDEFINED && (cmode & NC_NETCDF4))
2072  return NC_ENOTBUILT;
2073 #endif
2074 #ifdef USE_PNETCDF
2075  if (model == NC_FORMATX_UNDEFINED && useparallel)
2076  /* PnetCDF is used for parallel io on CDF-1, CDF-2, and CDF-5 */
2077  model = NC_FORMATX_PNETCDF;
2078 #else
2079  if (model == NC_FORMATX_UNDEFINED && useparallel)
2080  return NC_ENOTBUILT;
2081 #endif
2082 
2083  /* Check default format (not formatx) */
2084  if (!fIsSet(cmode, NC_64BIT_OFFSET) && !fIsSet(cmode, NC_64BIT_DATA) &&
2085  !fIsSet(cmode, NC_CLASSIC_MODEL) && !fIsSet(cmode, NC_NETCDF4)) {
2086  /* if no file format flag is set in cmode, use default */
2087  int format = nc_get_default_format();
2088  switch (format) {
2089 #ifdef USE_NETCDF4
2090  case NC_FORMAT_NETCDF4:
2091  cmode |= NC_NETCDF4;
2092  if (model == NC_FORMATX_UNDEFINED) model = NC_FORMATX_NC4;
2093  break;
2095  cmode |= NC_NETCDF4 | NC_CLASSIC_MODEL;
2096  if (model == NC_FORMATX_UNDEFINED) model = NC_FORMATX_NC4;
2097  break;
2098 #endif
2099  case NC_FORMAT_CDF5:
2100  cmode |= NC_64BIT_DATA;
2101  break;
2103  cmode |= NC_64BIT_OFFSET;
2104  break;
2105  case NC_FORMAT_CLASSIC: break;
2106  default: break;
2107  }
2108  }
2109 
2110  /* default model */
2111  if (model == NC_FORMATX_UNDEFINED) {
2112  if (useparallel)
2113  model = NC_FORMATX_PNETCDF;
2114  else
2115  model = NC_FORMATX_NC3;
2116  }
2117 
2118 #ifndef ENABLE_CDF5
2119  if (model == NC_FORMATX_NC3 && (cmode & NC_64BIT_DATA))
2120  return NC_ENOTBUILT;
2121 #endif
2122 
2123  /* Figure out what dispatcher to use */
2124  if (model == NC_FORMATX_NC4)
2125 #ifdef USE_NETCDF4
2126  dispatcher = NC4_dispatch_table;
2127 #else
2128  return NC_ENOTBUILT;
2129 #endif
2130  else if (model == NC_FORMATX_PNETCDF)
2131 #ifdef USE_PNETCDF
2132  dispatcher = NCP_dispatch_table;
2133 #else
2134  return NC_ENOTBUILT;
2135 #endif
2136  else if (model == NC_FORMATX_NC3)
2137  dispatcher = NC3_dispatch_table;
2138  else {
2139  nullfree(path);
2140  return NC_ENOTNC;
2141  }
2142 
2143  /* Create the NC* instance and insert its dispatcher */
2144  stat = new_NC(dispatcher,path,cmode,model,&ncp);
2145  nullfree(path); path = NULL; /* no longer needed */
2146 
2147  if(stat) return stat;
2148 
2149  /* Add to list of known open files and define ext_ncid */
2150  add_to_NCList(ncp);
2151 
2152 #ifdef USE_REFCOUNT
2153  /* bump the refcount */
2154  ncp->refcount++;
2155 #endif
2156 
2157  /* Assume create will fill in remaining ncp fields */
2158  if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp,
2159  parameters, dispatcher, ncp))) {
2160  del_from_NCList(ncp); /* oh well */
2161  free_NC(ncp);
2162  } else {
2163  if(ncidp)*ncidp = ncp->ext_ncid;
2164  }
2165  return stat;
2166 }
2167 
2191 int
2192 NC_open(const char *path0, int omode, int basepe, size_t *chunksizehintp,
2193  int useparallel, void* parameters, int *ncidp)
2194 {
2195  int stat = NC_NOERR;
2196  NC* ncp = NULL;
2197  NC_Dispatch* dispatcher = NULL;
2198  int inmemory = 0;
2199  int diskless = 0;
2200  int mmap = 0;
2201  /* Need pieces of information for now to decide model*/
2202  int model = 0;
2203  int isurl = 0;
2204  int version = 0;
2205  char* path = NULL;
2206 
2207  TRACE(nc_open);
2208  if(!NC_initialized) {
2209  stat = nc_initialize();
2210  if(stat) return stat;
2211  }
2212 
2213  /* Fix the inmemory related flags */
2214  mmap = ((omode & NC_MMAP) == NC_MMAP);
2215  diskless = ((omode & NC_DISKLESS) == NC_DISKLESS);
2216  inmemory = ((omode & NC_INMEMORY) == NC_INMEMORY);
2217 
2218  if(mmap && inmemory) /* cannot have both */
2219  return NC_EINMEMORY;
2220  if(mmap && diskless) /* cannot have both */
2221  return NC_EDISKLESS;
2222 
2223  /* Attempt to do file path conversion: note that this will do
2224  nothing if path is a 'file:...' url, so it will need to be
2225  repeated in protocol code: libdap2 and libdap4
2226  */
2227 
2228 #ifdef WINPATH
2229  path = NCpathcvt(path0);
2230 #else
2231  path = nulldup(path0);
2232 #endif
2233 
2234 #ifdef USE_REFCOUNT
2235  /* If this path is already open, then bump the refcount and return it */
2236  ncp = find_in_NCList_by_name(path);
2237  if(ncp != NULL) {
2238  nullfree(path);
2239  ncp->refcount++;
2240  if(ncidp) *ncidp = ncp->ext_ncid;
2241  return NC_NOERR;
2242  }
2243 #endif
2244 
2245  if(!inmemory) {
2246  char* newpath = NULL;
2247  model = NC_urlmodel(path,omode,&newpath);
2248  isurl = (model != 0);
2249  if(isurl) {
2250  nullfree(path);
2251  path = newpath;
2252  } else
2253  nullfree(newpath);
2254  }
2255 
2256 #ifdef USE_NETCDF4
2257  /* Check for use of user-defined format 0. */
2258  if (omode & NC_UDF0)
2259  {
2260  if (!UDF0_dispatch_table)
2261  return NC_EINVAL;
2262  model = NC_FORMATX_UDF0;
2263  dispatcher = UDF0_dispatch_table;
2264  }
2265 
2266  /* Check for use of user-defined format 1. */
2267  if (omode & NC_UDF1)
2268  {
2269  if (!UDF1_dispatch_table)
2270  return NC_EINVAL;
2271  model = NC_FORMATX_UDF1;
2272  dispatcher = UDF1_dispatch_table;
2273  }
2274 #endif /* USE_NETCDF4 */
2275 
2276  if(model == 0) {
2277  version = 0;
2278  /* Try to find dataset type */
2279  int flags = omode;
2280  stat = NC_check_file_type(path,flags,useparallel,parameters,&model,&version);
2281  if(stat == NC_NOERR) {
2282  if(model == 0) {
2283  nullfree(path);
2284  return NC_ENOTNC;
2285  }
2286  } else {
2287  /* presumably not a netcdf file */
2288  nullfree(path);
2289  return stat;
2290  }
2291  }
2292 
2293  if(model == 0) {
2294  fprintf(stderr,"Model == 0\n");
2295  return NC_ENOTNC;
2296  }
2297 
2298  /* Suppress unsupported formats */
2299  {
2300  int hdf5built = 0;
2301  int hdf4built = 0;
2302  int cdf5built = 0;
2303 #ifdef USE_NETCDF4
2304  hdf5built = 1;
2305  #ifdef USEHDF4
2306  hdf4built = 1;
2307  #endif
2308 #endif
2309 #ifdef ENABLE_CDF5
2310  cdf5built = 1;
2311 #endif
2312  if(!hdf5built && model == NC_FORMATX_NC4) {
2313  free(path);
2314  return NC_ENOTBUILT;
2315  }
2316  if(!hdf4built && model == NC_FORMATX_NC4 && version == 4) {
2317  free(path);
2318  return NC_ENOTBUILT;
2319  }
2320  if(!cdf5built && model == NC_FORMATX_NC3 && version == 5) {
2321  free(path);
2322  return NC_ENOTBUILT;
2323  }
2324  }
2325 
2326  /* Force flag consistency */
2327  if(model == NC_FORMATX_NC4 || model == NC_FORMATX_NC_HDF4 || model == NC_FORMATX_DAP4 ||
2328  model == NC_FORMATX_UDF0 || model == NC_FORMATX_UDF1)
2329  omode |= NC_NETCDF4;
2330  else if(model == NC_FORMATX_DAP2) {
2331  omode &= ~NC_NETCDF4;
2332  omode &= ~NC_64BIT_OFFSET;
2333  } else if(model == NC_FORMATX_NC3) {
2334  omode &= ~NC_NETCDF4; /* must be netcdf-3 (CDF-1, CDF-2, CDF-5) */
2335  if(version == 2) omode |= NC_64BIT_OFFSET;
2336  else if(version == 5) omode |= NC_64BIT_DATA;
2337  } else if(model == NC_FORMATX_PNETCDF) {
2338  omode &= ~NC_NETCDF4; /* must be netcdf-3 (CDF-1, CDF-2, CDF-5) */
2339  if(version == 2) omode |= NC_64BIT_OFFSET;
2340  else if(version == 5) omode |= NC_64BIT_DATA;
2341  }
2342 
2343  /* Figure out what dispatcher to use */
2344  if (!dispatcher) {
2345  switch (model) {
2346 #if defined(ENABLE_DAP)
2347  case NC_FORMATX_DAP2:
2348  dispatcher = NCD2_dispatch_table;
2349  break;
2350 #endif
2351 #if defined(ENABLE_DAP4)
2352  case NC_FORMATX_DAP4:
2353  dispatcher = NCD4_dispatch_table;
2354  break;
2355 #endif
2356 #if defined(USE_PNETCDF)
2357  case NC_FORMATX_PNETCDF:
2358  dispatcher = NCP_dispatch_table;
2359  break;
2360 #endif
2361 #if defined(USE_NETCDF4)
2362  case NC_FORMATX_NC4:
2363  dispatcher = NC4_dispatch_table;
2364  break;
2365 #endif
2366 #if defined(USE_HDF4)
2367  case NC_FORMATX_NC_HDF4:
2368  dispatcher = HDF4_dispatch_table;
2369  break;
2370 #endif
2371 #ifdef USE_NETCDF4
2372  case NC_FORMATX_UDF0:
2373  dispatcher = UDF0_dispatch_table;
2374  break;
2375  case NC_FORMATX_UDF1:
2376  dispatcher = UDF1_dispatch_table;
2377  break;
2378 #endif /* USE_NETCDF4 */
2379  case NC_FORMATX_NC3:
2380  dispatcher = NC3_dispatch_table;
2381  break;
2382  default:
2383  nullfree(path);
2384  return NC_ENOTNC;
2385  }
2386  }
2387 
2388  /* If we can't figure out what dispatch table to use, give up. */
2389  if (!dispatcher) {
2390  nullfree(path);
2391  return NC_ENOTNC;
2392  }
2393 
2394  /* Create the NC* instance and insert its dispatcher */
2395  stat = new_NC(dispatcher,path,omode,model,&ncp);
2396  nullfree(path); path = NULL; /* no longer need path */
2397  if(stat) return stat;
2398 
2399  /* Add to list of known open files */
2400  add_to_NCList(ncp);
2401 
2402 #ifdef USE_REFCOUNT
2403  /* bump the refcount */
2404  ncp->refcount++;
2405 #endif
2406 
2407  /* Assume open will fill in remaining ncp fields */
2408  stat = dispatcher->open(ncp->path, omode, basepe, chunksizehintp,
2409  parameters, dispatcher, ncp);
2410  if(stat == NC_NOERR) {
2411  if(ncidp) *ncidp = ncp->ext_ncid;
2412  } else {
2413  del_from_NCList(ncp);
2414  free_NC(ncp);
2415  }
2416  return stat;
2417 }
2418 
2419 /*Provide an internal function for generating pseudo file descriptors
2420  for systems that are not file based (e.g. dap, memio).
2421 */
2422 
2424 static int pseudofd = 0;
2425 
2433 int
2434 nc__pseudofd(void)
2435 {
2436  if(pseudofd == 0) {
2437  int maxfd = 32767; /* default */
2438 #ifdef HAVE_GETRLIMIT
2439  struct rlimit rl;
2440  if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
2441  if(rl.rlim_max != RLIM_INFINITY)
2442  maxfd = (int)rl.rlim_max;
2443  if(rl.rlim_cur != RLIM_INFINITY)
2444  maxfd = (int)rl.rlim_cur;
2445  }
2446  pseudofd = maxfd+1;
2447 #endif
2448  }
2449  return pseudofd++;
2450 }
2451 
2457 static int
2458 openmagic(struct MagicFile* file)
2459 {
2460  int status = NC_NOERR;
2461  assert((file->inmemory) ? file->parameters != NULL : 1);
2462  if(file->inmemory) {
2463  /* Get its length */
2464  NC_memio* meminfo = (NC_memio*)file->parameters;
2465  file->filelen = (long long)meminfo->size;
2466  goto done;
2467  }
2468 #ifdef USE_PARALLEL
2469  if (file->use_parallel) {
2470  int retval;
2471  MPI_Offset size;
2472  assert(file->parameters);
2473  if((retval = MPI_File_open(((NC_MPI_INFO*)file->parameters)->comm,
2474  (char*)file->path,MPI_MODE_RDONLY,
2475  ((NC_MPI_INFO*)file->parameters)->info,
2476  &file->fh)) != MPI_SUCCESS) {
2477 #ifdef MPI_ERR_NO_SUCH_FILE
2478  int errorclass;
2479  MPI_Error_class(retval, &errorclass);
2480  if (errorclass == MPI_ERR_NO_SUCH_FILE)
2481 #ifdef NC_ENOENT
2482  status = NC_ENOENT;
2483 #else
2484  status = errno;
2485 #endif
2486  else
2487 #endif
2488  status = NC_EPARINIT;
2489  goto done;
2490  }
2491  /* Get its length */
2492  if((retval=MPI_File_get_size(file->fh, &size)) != MPI_SUCCESS)
2493  {status = NC_EPARINIT; goto done;}
2494  file->filelen = (long long)size;
2495  goto done;
2496  }
2497 #endif /* USE_PARALLEL */
2498  {
2499  if(file->path == NULL || strlen(file->path)==0)
2500  {status = NC_EINVAL; goto done;}
2501 #ifdef _MSC_VER
2502  file->fp = fopen(file->path, "rb");
2503 #else
2504  file->fp = fopen(file->path, "r");
2505 #endif
2506  if(file->fp == NULL)
2507  {status = errno; goto done;}
2508  /* Get its length */
2509  {
2510  int fd = fileno(file->fp);
2511 #ifdef _MSC_VER
2512  __int64 len64 = _filelengthi64(fd);
2513  if(len64 < 0)
2514  {status = errno; goto done;}
2515  file->filelen = (long long)len64;
2516 #else
2517  off_t size;
2518  size = lseek(fd, 0, SEEK_END);
2519  if(size == -1)
2520  {status = errno; goto done;}
2521  file->filelen = (long long)size;
2522 #endif
2523  rewind(file->fp);
2524  }
2525  goto done;
2526  }
2527 
2528 done:
2529  return status;
2530 }
2531 
2532 static int
2533 readmagic(struct MagicFile* file, long pos, char* magic)
2534 {
2535  int status = NC_NOERR;
2536  memset(magic,0,MAGIC_NUMBER_LEN);
2537  if(file->inmemory) {
2538  char* mempos;
2539  NC_memio* meminfo = (NC_memio*)file->parameters;
2540  if((pos + MAGIC_NUMBER_LEN) > meminfo->size)
2541  {status = NC_EINMEMORY; goto done;}
2542  mempos = ((char*)meminfo->memory) + pos;
2543  memcpy((void*)magic,mempos,MAGIC_NUMBER_LEN);
2544 #ifdef DEBUG
2545  printmagic("XXX: readmagic",magic,file);
2546 #endif
2547  goto done;
2548  }
2549 #ifdef USE_PARALLEL
2550  if (file->use_parallel) {
2551  MPI_Status mstatus;
2552  int retval;
2553  if((retval = MPI_File_read_at_all(file->fh, pos, magic,
2554  MAGIC_NUMBER_LEN, MPI_CHAR, &mstatus)) != MPI_SUCCESS)
2555  {status = NC_EPARINIT; goto done;}
2556  goto done;
2557  }
2558 #endif /* USE_PARALLEL */
2559  {
2560  int count;
2561  int i = fseek(file->fp,pos,SEEK_SET);
2562  if(i < 0)
2563  {status = errno; goto done;}
2564  for(i=0;i<MAGIC_NUMBER_LEN;) {/* make sure to read proper # of bytes */
2565  count=fread(&magic[i],1,(size_t)(MAGIC_NUMBER_LEN-i),file->fp);
2566  if(count == 0 || ferror(file->fp))
2567  {status = errno; goto done;}
2568  i += count;
2569  }
2570  goto done;
2571  }
2572 done:
2573  if(file && file->fp) clearerr(file->fp);
2574  return status;
2575 }
2576 
2586 static int
2587 closemagic(struct MagicFile* file)
2588 {
2589  int status = NC_NOERR;
2590  if(file->inmemory) goto done; /* noop*/
2591 #ifdef USE_PARALLEL
2592  if (file->use_parallel) {
2593  int retval;
2594  if((retval = MPI_File_close(&file->fh)) != MPI_SUCCESS)
2595  {status = NC_EPARINIT; goto done;}
2596  goto done;
2597  }
2598 #endif
2599  {
2600  if(file->fp) fclose(file->fp);
2601  goto done;
2602  }
2603 done:
2604  return status;
2605 }
2606 
2607 #ifdef DEBUG
2608 static void
2609 printmagic(const char* tag, char* magic, struct MagicFile* f)
2610 {
2611  int i;
2612  fprintf(stderr,"%s: inmem=%d ispar=%d magic=",tag,f->inmemory,f->use_parallel);
2613  for(i=0;i<MAGIC_NUMBER_LEN;i++) {
2614  unsigned int c = (unsigned int)magic[i];
2615  c = c & 0x000000FF;
2616  if(c == '\n')
2617  fprintf(stderr," 0x%0x/'\\n'",c);
2618  else if(c == '\r')
2619  fprintf(stderr," 0x%0x/'\\r'",c);
2620  else if(c < ' ')
2621  fprintf(stderr," 0x%0x/'?'",c);
2622  else
2623  fprintf(stderr," 0x%0x/'%c'",c,c);
2624  }
2625  fprintf(stderr,"\n");
2626  fflush(stderr);
2627 }
2628 #endif
#define NC_MAX_MAGIC_NUMBER_LEN
Max len of user-defined format magic number.
Definition: netcdf.h:164
#define NC_ENFILE
Too many netcdfs open.
Definition: netcdf.h:330
int nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number)
Add handling of user-defined format.
Definition: dfile.c:128
int NC_initialized
True when dispatch table is initialized.
int nc_close_memio(int ncid, NC_memio *memio)
Do a normal close (see nc_close()) on an in-memory dataset, then return a copy of the final memory co...
Definition: dfile.c:1527
#define NC_FORMATX_NC4
alias
Definition: netcdf.h:210
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:137
Main header file for in-memory (diskless) functionality.
int nc_redef(int ncid)
Put open netcdf dataset into define mode.
Definition: dfile.c:1119
int nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, size_t r_align)
Leave define mode with performance tuning.
Definition: dfile.c:1274
#define NC_UDF1
User-defined format 1.
Definition: netcdf.h:135
#define NC_INMEMORY
Read from memory.
Definition: netcdf.h:160
#define NC_MPIIO
Turn on MPI I/O.
Definition: netcdf.h:154
int nc_open_memio(const char *path, int omode, NC_memio *params, int *ncidp)
Open a netCDF file with the contents taken from a block of memory.
Definition: dfile.c:997
int nc_inq_format(int ncid, int *formatp)
Inquire about the binary format of a netCDF file as presented by the API.
Definition: dfile.c:1721
int nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
Inquire about a file or group.
Definition: dfile.c:1809
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:24
#define NC_64BIT_OFFSET
Use large (64-bit) file offsets.
Definition: netcdf.h:138
int nc__open(const char *path, int omode, size_t *chunksizehintp, int *ncidp)
Open a netCDF file with extra performance parameters for the classic library.
Definition: dfile.c:877
#define NC_UDF0
User-defined format 0.
Definition: netcdf.h:134
int nc_inq_format_extended(int ncid, int *formatp, int *modep)
Obtain more detailed (vis-a-vis nc_inq_format) format information about an open dataset.
Definition: dfile.c:1756
#define NC_ENOTNC
Not a netcdf file.
Definition: netcdf.h:378
#define NC_FORMAT_CDF5
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition: netcdf.h:186
#define NC_64BIT_DATA
CDF-5 format: classic model but 64 bit dimensions and sizes.
Definition: netcdf.h:131
#define NC_ENOTBUILT
Attempt to use feature that was not turned on when netCDF was built.
Definition: netcdf.h:462
int nc_close(int ncid)
Close an open netCDF dataset.
Definition: dfile.c:1462
#define NC_EDISKLESS
Error in using diskless access.
Definition: netcdf.h:463
int nc_abort(int ncid)
No longer necessary for user to invoke manually.
Definition: dfile.c:1403
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:364
int nc_open_mem(const char *path, int omode, size_t size, void *memory, int *ncidp)
Open a netCDF file with the contents taken from a block of memory.
Definition: dfile.c:932
#define NC_SIZEHINT_DEFAULT
Let nc__create() or nc__open() figure out a suitable buffer size.
Definition: netcdf.h:236
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:332
#define NC_EINMEMORY
In-memory file error.
Definition: netcdf.h:470
int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
Definition: dfile.c:1648
#define NC_FORMATX_UDF0
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:215
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:272
#define NC_NAT
Not A Type.
Definition: netcdf.h:33
int nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
Inquire about a type.
Definition: dfile.c:1902
#define NC_FORMATX_DAP2
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:213
#define NC_FORMATX_NC3
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:208
#define NC_EPARINIT
Error initializing for parallel access.
Definition: netcdf.h:449
#define NC_NETCDF4
Use netCDF-4/HDF5 format.
Definition: netcdf.h:150
int nc__create(const char *path, int cmode, size_t initialsz, size_t *chunksizehintp, int *ncidp)
Create a netCDF file with some extra parameters controlling classic file caching. ...
Definition: dfile.c:626
#define NC_FORMAT_NETCDF4_CLASSIC
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition: netcdf.h:182
#define NC_FORMATX_NC_HDF4
netCDF-4 subset of HDF4
Definition: netcdf.h:211
int nc_open(const char *path, int omode, int *ncidp)
Open an existing netCDF file.
Definition: dfile.c:820
#define NC_FORMATX_UDF1
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:216
#define NC_FORMAT_NETCDF4
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition: netcdf.h:181
#define NC_CDF5
Alias NC_CDF5 to NC_64BIT_DATA.
Definition: netcdf.h:132
#define NC_WRITE
Set read-write access for nc_open().
Definition: netcdf.h:123
int nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
Inquire about user-defined format.
Definition: dfile.c:174
int nc_create_mem(const char *path, int mode, size_t initialsize, int *ncidp)
Create a netCDF file with the contents stored in memory.
Definition: dfile.c:672
int nc_inq_path(int ncid, size_t *pathlen, char *path)
Get the file pathname (or the opendap URL) which was used to open/create the ncid&#39;s file...
Definition: dfile.c:1054
#define NC_NOERR
No Error.
Definition: netcdf.h:322
int nc_inq_nvars(int ncid, int *nvarsp)
Learn the number of variables in a file or group.
Definition: dfile.c:1828
#define NC_DISKLESS
Use diskless file.
Definition: netcdf.h:128
static int check_create_mode(int mode)
Check the create mode parameter for sanity.
Definition: dfile.c:1942
#define NC_FORMATX_DAP4
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:214
int nc_enddef(int ncid)
Leave define mode.
Definition: dfile.c:1183
#define NC_FORMATX_PNETCDF
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:212
static int NC_interpret_magic_number(char *magic, int *model, int *version)
Interpret the magic number found in the header of a netCDF file.
Definition: dfile.c:215
#define NC_FORMAT_64BIT_OFFSET
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition: netcdf.h:179
#define NC_MMAP
Definition: netcdf.h:129
static int closemagic(struct MagicFile *file)
Close the file opened to check for magic number.
Definition: dfile.c:2587
#define NC_FORMATX_UNDEFINED
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
Definition: netcdf.h:217
#define NC_FORMAT_CLASSIC
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition: netcdf.h:173
int nc_sync(int ncid)
Synchronize an open netcdf dataset to disk.
Definition: dfile.c:1351
int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
Definition: dfile.c:554

Return to the Main Unidata NetCDF page.
Generated on Tue Nov 20 2018 06:04:35 for NetCDF. NetCDF is a Unidata library.