NetCDF 4.10.0
Loading...
Searching...
No Matches
dfile.c
Go to the documentation of this file.
1
13#include "config.h"
14#include <stdlib.h>
15#ifdef HAVE_STRING_H
16#include <string.h>
17#endif
18#ifdef HAVE_SYS_RESOURCE_H
19#include <sys/resource.h>
20#endif
21#ifdef HAVE_SYS_TYPES_H
22#include <sys/types.h>
23#endif
24#ifdef HAVE_SYS_STAT_H
25#include <sys/stat.h>
26#endif
27
28#ifdef HAVE_UNISTD_H
29#include <unistd.h> /* lseek() */
30#endif
31
32#ifdef HAVE_STDIO_H
33#include <stdio.h>
34#endif
35
36#include "ncdispatch.h"
37#include "netcdf_mem.h"
38#include "ncpathmgr.h"
39#include "fbits.h"
40
41#undef DEBUG
42
43#ifndef nulldup
44 #define nulldup(s) ((s)?strdup(s):NULL)
45#endif
46
47
48/* User-defined formats - expanded from 2 to 10 slots.
49 * These arrays store dispatch tables and magic numbers for up to 10 custom formats.
50 * Array-based design replaces the previous individual UDF0/UDF1 global variables. */
51NC_Dispatch *UDF_dispatch_tables[NC_MAX_UDF_FORMATS] = {NULL};
52char UDF_magic_numbers[NC_MAX_UDF_FORMATS][NC_MAX_MAGIC_NUMBER_LEN + 1] = {{0}};
53
59static int udf_mode_to_index(int mode_flag) {
60 int count = 0;
61 int index = -1;
62
63 /* Count how many UDF flags are set and remember the index */
64 if (fIsSet(mode_flag, NC_UDF0)) { count++; index = 0; }
65 if (fIsSet(mode_flag, NC_UDF1)) { count++; index = 1; }
66 if (fIsSet(mode_flag, NC_UDF2)) { count++; index = 2; }
67 if (fIsSet(mode_flag, NC_UDF3)) { count++; index = 3; }
68 if (fIsSet(mode_flag, NC_UDF4)) { count++; index = 4; }
69 if (fIsSet(mode_flag, NC_UDF5)) { count++; index = 5; }
70 if (fIsSet(mode_flag, NC_UDF6)) { count++; index = 6; }
71 if (fIsSet(mode_flag, NC_UDF7)) { count++; index = 7; }
72 if (fIsSet(mode_flag, NC_UDF8)) { count++; index = 8; }
73 if (fIsSet(mode_flag, NC_UDF9)) { count++; index = 9; }
74
75 /* Only one UDF flag should be set at a time */
76 if (count != 1)
77 return -1;
78
79 return index;
80}
81
87static int udf_formatx_to_index(int formatx) {
88 /* UDF0 and UDF1 are sequential (8, 9) */
89 if (formatx >= NC_FORMATX_UDF0 && formatx <= NC_FORMATX_UDF1)
90 return formatx - NC_FORMATX_UDF0;
91 /* UDF2-UDF9 start at 11 (skipping NCZARR at 10) */
92 if (formatx >= NC_FORMATX_UDF2 && formatx <= NC_FORMATX_UDF9)
93 return formatx - NC_FORMATX_UDF2 + 2;
94 return -1;
95}
96
97/**************************************************/
98
99
165int
166nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number)
167{
168 int udf_index;
169
170 /* Check inputs. */
171 if (!dispatch_table)
172 return NC_EINVAL;
173 if (magic_number && strlen(magic_number) > NC_MAX_MAGIC_NUMBER_LEN)
174 return NC_EINVAL;
175
176 /* Check the version of the dispatch table provided. */
177 if (dispatch_table->dispatch_version != NC_DISPATCH_VERSION)
178 return NC_EINVAL;
179 /* user defined magic numbers not allowed with netcdf3 modes */
180 if (magic_number && (fIsSet(mode_flag, NC_64BIT_OFFSET) ||
181 fIsSet(mode_flag, NC_64BIT_DATA) ||
182 (fIsSet(mode_flag, NC_CLASSIC_MODEL) &&
183 !fIsSet(mode_flag, NC_NETCDF4))))
184 return NC_EINVAL;
185
186 /* Get the UDF index from the mode flag. */
187 udf_index = udf_mode_to_index(mode_flag);
188 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS)
189 return NC_EINVAL;
190
191 /* Retain a pointer to the dispatch_table and a copy of the magic
192 * number, if one was provided. */
193 UDF_dispatch_tables[udf_index] = dispatch_table;
194 if (magic_number) {
195 strncpy(UDF_magic_numbers[udf_index], magic_number, NC_MAX_MAGIC_NUMBER_LEN);
196 /* Ensure null-termination since strncpy doesn't guarantee it if source >= max length */
197 UDF_magic_numbers[udf_index][NC_MAX_MAGIC_NUMBER_LEN] = '\0';
198 }
199
200 return NC_NOERR;
201}
202
219int
220nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
221{
222 int udf_index;
223
224 /* Get the UDF index from the mode flag. */
225 udf_index = udf_mode_to_index(mode_flag);
226 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS)
227 return NC_EINVAL;
228
229 /* Return the dispatch table and magic number. */
230 if (dispatch_table)
231 *dispatch_table = UDF_dispatch_tables[udf_index];
232 if (magic_number)
233 strncpy(magic_number, UDF_magic_numbers[udf_index], NC_MAX_MAGIC_NUMBER_LEN);
234
235 return NC_NOERR;
236}
237
431int
432nc_create(const char *path, int cmode, int *ncidp)
433{
434 return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
435}
436
503int
504nc__create(const char *path, int cmode, size_t initialsz,
505 size_t *chunksizehintp, int *ncidp)
506{
507 return NC_create(path, cmode, initialsz, 0,
508 chunksizehintp, 0, NULL, ncidp);
509}
510
549int
550nc_create_mem(const char* path, int mode, size_t initialsize, int* ncidp)
551{
552 if(mode & NC_MMAP) return NC_EINVAL;
553 mode |= NC_INMEMORY; /* Specifically, do not set NC_DISKLESS */
554 return NC_create(path, mode, initialsize, 0, NULL, 0, NULL, ncidp);
555}
556
576int
577nc__create_mp(const char *path, int cmode, size_t initialsz,
578 int basepe, size_t *chunksizehintp, int *ncidp)
579{
580 return NC_create(path, cmode, initialsz, basepe,
581 chunksizehintp, 0, NULL, ncidp);
582}
583
697int
698nc_open(const char *path, int omode, int *ncidp)
699{
700 return NC_open(path, omode, 0, NULL, 0, NULL, ncidp);
701}
702
754int
755nc__open(const char *path, int omode,
756 size_t *chunksizehintp, int *ncidp)
757{
758 /* this API is for non-parallel access.
759 * Note nc_open_par() also calls NC_open().
760 */
761 return NC_open(path, omode, 0, chunksizehintp, 0, NULL, ncidp);
762}
763
809int
810nc_open_mem(const char* path, int omode, size_t size, void* memory, int* ncidp)
811{
812 NC_memio meminfo;
813
814 /* Sanity checks */
815 if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL)
816 return NC_EINVAL;
817 if(omode & (NC_WRITE|NC_MMAP))
818 return NC_EINVAL;
819 omode |= (NC_INMEMORY); /* Note: NC_INMEMORY and NC_DISKLESS are mutually exclusive*/
820 meminfo.size = size;
821 meminfo.memory = memory;
822 meminfo.flags = NC_MEMIO_LOCKED;
823 return NC_open(path, omode, 0, NULL, 0, &meminfo, ncidp);
824}
825
874int
875nc_open_memio(const char* path, int omode, NC_memio* params, int* ncidp)
876{
877 /* Sanity checks */
878 if(path == NULL || params == NULL)
879 return NC_EINVAL;
880 if(params->memory == NULL || params->size < MAGIC_NUMBER_LEN)
881 return NC_EINVAL;
882
883 if(omode & NC_MMAP)
884 return NC_EINVAL;
885 omode |= (NC_INMEMORY);
886 return NC_open(path, omode, 0, NULL, 0, params, ncidp);
887}
888
907int
908nc__open_mp(const char *path, int omode, int basepe,
909 size_t *chunksizehintp, int *ncidp)
910{
911 return NC_open(path, omode, basepe, chunksizehintp, 0, NULL, ncidp);
912}
913
931int
932nc_inq_path(int ncid, size_t *pathlen, char *path)
933{
934 NC* ncp;
935 int stat = NC_NOERR;
936 if ((stat = NC_check_id(ncid, &ncp)))
937 return stat;
938 if(ncp->path == NULL) {
939 if(pathlen) *pathlen = 0;
940 if(path) path[0] = '\0';
941 } else {
942 if (pathlen) *pathlen = strlen(ncp->path);
943 if (path) strcpy(path, ncp->path);
944 }
945 return stat;
946}
947
996int
997nc_redef(int ncid)
998{
999 NC* ncp;
1000 int stat = NC_check_id(ncid, &ncp);
1001 if(stat != NC_NOERR) return stat;
1002 return ncp->dispatch->redef(ncid);
1003}
1004
1060int
1061nc_enddef(int ncid)
1062{
1063 int status = NC_NOERR;
1064 NC *ncp;
1065 status = NC_check_id(ncid, &ncp);
1066 if(status != NC_NOERR) return status;
1067 return ncp->dispatch->_enddef(ncid,0,1,0,1);
1068}
1069
1151int
1152nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree,
1153 size_t r_align)
1154{
1155 NC* ncp;
1156 int stat = NC_check_id(ncid, &ncp);
1157 if(stat != NC_NOERR) return stat;
1158 return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
1159}
1160
1228int
1229nc_sync(int ncid)
1230{
1231 NC* ncp;
1232 int stat = NC_check_id(ncid, &ncp);
1233 if(stat != NC_NOERR) return stat;
1234 return ncp->dispatch->sync(ncid);
1235}
1236
1280int
1281nc_abort(int ncid)
1282{
1283 NC* ncp;
1284 int stat = NC_check_id(ncid, &ncp);
1285 if(stat != NC_NOERR) return stat;
1286
1287 stat = ncp->dispatch->abort(ncid);
1288 del_from_NCList(ncp);
1289 free_NC(ncp);
1290 return stat;
1291}
1292
1333int
1334nc_close(int ncid)
1335{
1336 NC* ncp;
1337 int stat = NC_check_id(ncid, &ncp);
1338 if(stat != NC_NOERR) return stat;
1339
1340 stat = ncp->dispatch->close(ncid,NULL);
1341 /* Remove from the nc list */
1342 if (!stat)
1343 {
1344 del_from_NCList(ncp);
1345 free_NC(ncp);
1346 }
1347 return stat;
1348}
1349
1392int
1393nc_close_memio(int ncid, NC_memio* memio)
1394{
1395 NC* ncp;
1396 int stat = NC_check_id(ncid, &ncp);
1397 if(stat != NC_NOERR) return stat;
1398
1399 stat = ncp->dispatch->close(ncid,memio);
1400 /* Remove from the nc list */
1401 if (!stat)
1402 {
1403 del_from_NCList(ncp);
1404 free_NC(ncp);
1405 }
1406 return stat;
1407}
1408
1507int
1508nc_set_fill(int ncid, int fillmode, int *old_modep)
1509{
1510 NC* ncp;
1511 int stat = NC_check_id(ncid, &ncp);
1512 if(stat != NC_NOERR) return stat;
1513 return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1514}
1515
1530int
1531nc_inq_base_pe(int ncid, int *pe)
1532{
1533 NC* ncp;
1534 int stat = NC_check_id(ncid, &ncp);
1535 if(stat != NC_NOERR) return stat;
1536 if (pe) *pe = 0;
1537 return NC_NOERR;
1538}
1539
1554int
1555nc_set_base_pe(int ncid, int pe)
1556{
1557 NC* ncp;
1558 int stat = NC_check_id(ncid, &ncp);
1559 if(stat != NC_NOERR) return stat;
1560 return NC_NOERR;
1561}
1562
1580int
1581nc_inq_format(int ncid, int *formatp)
1582{
1583 NC* ncp;
1584 int stat = NC_check_id(ncid, &ncp);
1585 if(stat != NC_NOERR) return stat;
1586 return ncp->dispatch->inq_format(ncid,formatp);
1587}
1588
1615int
1616nc_inq_format_extended(int ncid, int *formatp, int *modep)
1617{
1618 NC* ncp;
1619 int stat = NC_check_id(ncid, &ncp);
1620 if(stat != NC_NOERR) return stat;
1621 return ncp->dispatch->inq_format_extended(ncid,formatp,modep);
1622}
1623
1668int
1669nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1670{
1671 NC* ncp;
1672 int stat = NC_check_id(ncid, &ncp);
1673 if(stat != NC_NOERR) return stat;
1674 return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1675}
1676
1687int
1688nc_inq_nvars(int ncid, int *nvarsp)
1689{
1690 NC* ncp;
1691 int stat = NC_check_id(ncid, &ncp);
1692 if(stat != NC_NOERR) return stat;
1693 return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1694}
1695
1761int
1762nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1763{
1764 NC* ncp;
1765 int stat;
1766
1767 /* Do a quick triage on xtype */
1768 if(xtype <= NC_NAT) return NC_EBADTYPE;
1769 /* For compatibility, we need to allow inq about
1770 atomic types, even if ncid is ill-defined */
1771 if(xtype <= ATOMICTYPEMAX4) {
1772 if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1773 if(size) *size = NC_atomictypelen(xtype);
1774 return NC_NOERR;
1775 }
1776 /* Apparently asking about a user defined type, so we need
1777 a valid ncid */
1778 stat = NC_check_id(ncid, &ncp);
1779 if(stat != NC_NOERR) /* bad ncid */
1780 return NC_EBADTYPE;
1781 /* have good ncid */
1782 return ncp->dispatch->inq_type(ncid,xtype,name,size);
1783}
1784
1808static int
1810{
1811 int mode_format;
1812 int use_mmap = 0;
1813 int inmemory = 0;
1814 int diskless = 0;
1815
1816 /* This is a clever check to see if more than one format bit is
1817 * set. */
1818 mode_format = (mode & NC_NETCDF4) | (mode & NC_64BIT_OFFSET) |
1819 (mode & NC_CDF5);
1820 if (mode_format && (mode_format & (mode_format - 1)))
1821 return NC_EINVAL;
1822
1823 use_mmap = ((mode & NC_MMAP) == NC_MMAP);
1824 inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY);
1825 diskless = ((mode & NC_DISKLESS) == NC_DISKLESS);
1826
1827 /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
1828 if(diskless && inmemory) return NC_EDISKLESS;
1829 if(diskless && use_mmap) return NC_EDISKLESS;
1830 if(inmemory && use_mmap) return NC_EINMEMORY;
1831
1832 /* mmap is not allowed for netcdf-4 */
1833 if(use_mmap && (mode & NC_NETCDF4)) return NC_EINVAL;
1834
1835#ifndef USE_NETCDF4
1836 /* If the user asks for a netCDF-4 file, and the library was built
1837 * without netCDF-4, then return an error.*/
1838 if (mode & NC_NETCDF4)
1839 return NC_ENOTBUILT;
1840#endif /* USE_NETCDF4 undefined */
1841
1842 /* Well I guess there is some sanity in the world after all. */
1843 return NC_NOERR;
1844}
1845
1873int
1874NC_create(const char *path0, int cmode, size_t initialsz,
1875 int basepe, size_t *chunksizehintp, int useparallel,
1876 void* parameters, int *ncidp)
1877{
1878 int stat = NC_NOERR;
1879 NC* ncp = NULL;
1880 const NC_Dispatch* dispatcher = NULL;
1881 char* path = NULL;
1882 NCmodel model;
1883 char* newpath = NULL;
1884
1885 TRACE(nc_create);
1886 if(path0 == NULL)
1887 {stat = NC_EINVAL; goto done;}
1888
1889 /* Check mode flag for sanity. */
1890 if ((stat = check_create_mode(cmode))) goto done;
1891
1892 /* Initialize the library. The available dispatch tables
1893 * will depend on how netCDF was built
1894 * (with/without netCDF-4, DAP, CDMREMOTE). */
1895 if(!NC_initialized) {
1896 if ((stat = nc_initialize())) goto done;
1897 }
1898
1899 {
1900 /* Skip past any leading whitespace in path */
1901 const unsigned char* p;
1902 for(p=(const unsigned char*)path0;*p;p++) {if(*p > ' ') break;}
1903 path = nulldup((const char*)p);
1904 }
1905
1906 memset(&model,0,sizeof(model));
1907 newpath = NULL;
1908 if((stat = NC_infermodel(path,&cmode,1,useparallel,NULL,&model,&newpath))) goto done;
1909 if(newpath) {
1910 nullfree(path);
1911 path = newpath;
1912 newpath = NULL;
1913 }
1914
1915 assert(model.format != 0 && model.impl != 0);
1916
1917 /* Now, check for NC_ENOTBUILT cases limited to create (so e.g. HDF4 is not listed) */
1918#ifndef USE_HDF5
1919 if (model.impl == NC_FORMATX_NC4)
1920 {stat = NC_ENOTBUILT; goto done;}
1921#endif
1922#ifndef USE_PNETCDF
1923 if (model.impl == NC_FORMATX_PNETCDF)
1924 {stat = NC_ENOTBUILT; goto done;}
1925#endif
1926#ifndef NETCDF_ENABLE_CDF5
1927 if (model.impl == NC_FORMATX_NC3 && (cmode & NC_64BIT_DATA))
1928 {stat = NC_ENOTBUILT; goto done;}
1929#endif
1930
1931 /* Figure out what dispatcher to use */
1932 switch (model.impl) {
1933#ifdef USE_HDF5
1934 case NC_FORMATX_NC4:
1935 dispatcher = HDF5_dispatch_table;
1936 break;
1937#endif
1938#ifdef USE_PNETCDF
1939 case NC_FORMATX_PNETCDF:
1940 dispatcher = NCP_dispatch_table;
1941 break;
1942#endif
1943#ifdef USE_NETCDF4
1944 case NC_FORMATX_UDF0:
1945 case NC_FORMATX_UDF1:
1946 case NC_FORMATX_UDF2:
1947 case NC_FORMATX_UDF3:
1948 case NC_FORMATX_UDF4:
1949 case NC_FORMATX_UDF5:
1950 case NC_FORMATX_UDF6:
1951 case NC_FORMATX_UDF7:
1952 case NC_FORMATX_UDF8:
1953 case NC_FORMATX_UDF9:
1954 {
1955 /* Convert format constant to array index and validate */
1956 int udf_index = udf_formatx_to_index(model.impl);
1957 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS) {
1958 stat = NC_EINVAL;
1959 goto done;
1960 }
1961 /* Get the dispatch table for this UDF slot */
1962 dispatcher = UDF_dispatch_tables[udf_index];
1963 /* Ensure the UDF format has been registered via nc_def_user_format() */
1964 if (!dispatcher) {
1965 stat = NC_ENOTBUILT;
1966 goto done;
1967 }
1968 }
1969 break;
1970#endif /* USE_NETCDF4 */
1971#ifdef NETCDF_ENABLE_NCZARR
1972 case NC_FORMATX_NCZARR:
1973 dispatcher = NCZ_dispatch_table;
1974 break;
1975#endif
1976 case NC_FORMATX_NC3:
1977 dispatcher = NC3_dispatch_table;
1978 break;
1979 default:
1980 {stat = NC_ENOTNC; goto done;}
1981 }
1982
1983 /* Create the NC* instance and insert its dispatcher and model */
1984 if((stat = new_NC(dispatcher,path,cmode,&ncp))) goto done;
1985
1986 /* Add to list of known open files and define ext_ncid */
1987 add_to_NCList(ncp);
1988
1989 /* Assume create will fill in remaining ncp fields */
1990 if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp,
1991 parameters, dispatcher, ncp->ext_ncid))) {
1992 del_from_NCList(ncp); /* oh well */
1993 free_NC(ncp);
1994 } else {
1995 if(ncidp)*ncidp = ncp->ext_ncid;
1996 }
1997done:
1998 nullfree(path);
1999 nullfree(newpath);
2000 return stat;
2001}
2002
2026int
2027NC_open(const char *path0, int omode, int basepe, size_t *chunksizehintp,
2028 int useparallel, void* parameters, int *ncidp)
2029{
2030 int stat = NC_NOERR;
2031 NC* ncp = NULL;
2032 const NC_Dispatch* dispatcher = NULL;
2033 int inmemory = 0;
2034 int diskless = 0;
2035 int use_mmap = 0;
2036 char* path = NULL;
2037 NCmodel model;
2038 char* newpath = NULL;
2039
2040 TRACE(nc_open);
2041 if(!NC_initialized) {
2042 stat = nc_initialize();
2043 if(stat) goto done;
2044 }
2045
2046 /* Check inputs. */
2047 if (!path0)
2048 {stat = NC_EINVAL; goto done;}
2049
2050 /* Capture the inmemory related flags */
2051 use_mmap = ((omode & NC_MMAP) == NC_MMAP);
2052 diskless = ((omode & NC_DISKLESS) == NC_DISKLESS);
2053 inmemory = ((omode & NC_INMEMORY) == NC_INMEMORY);
2054
2055 /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
2056 if(diskless && inmemory) {stat = NC_EDISKLESS; goto done;}
2057 if(diskless && use_mmap) {stat = NC_EDISKLESS; goto done;}
2058 if(inmemory && use_mmap) {stat = NC_EINMEMORY; goto done;}
2059
2060 /* mmap is not allowed for netcdf-4 */
2061 if(use_mmap && (omode & NC_NETCDF4)) {stat = NC_EINVAL; goto done;}
2062
2063 /* Attempt to do file path conversion: note that this will do
2064 nothing if path is a 'file:...' url, so it will need to be
2065 repeated in protocol code (e.g. libdap2, libdap4, etc).
2066 */
2067
2068 {
2069 /* Skip past any leading whitespace in path */
2070 const char* p;
2071 for(p=(const char*)path0;*p;p++) {if(*p < 0 || *p > ' ') break;}
2072 path = nulldup(p);
2073 }
2074
2075 memset(&model,0,sizeof(model));
2076 /* Infer model implementation and format, possibly by reading the file */
2077 if((stat = NC_infermodel(path,&omode,0,useparallel,parameters,&model,&newpath)))
2078 goto done;
2079 if(newpath) {
2080 nullfree(path);
2081 path = newpath;
2082 newpath = NULL;
2083 }
2084
2085 /* Still no implementation, give up */
2086 if(model.impl == 0) {
2087#ifdef DEBUG
2088 fprintf(stderr,"implementation == 0\n");
2089#endif
2090 {stat = NC_ENOTNC; goto done;}
2091 }
2092
2093 /* Suppress unsupported formats */
2094#if 0
2095 /* (should be more compact, table-driven, way to do this) */
2096 {
2097 int hdf5built = 0;
2098 int hdf4built = 0;
2099 int cdf5built = 0;
2100 int udf0built = 0;
2101 int udf1built = 0;
2102 int nczarrbuilt = 0;
2103#ifdef USE_NETCDF4
2104 hdf5built = 1;
2105#endif
2106#ifdef USE_HDF4
2107 hdf4built = 1;
2108#endif
2109#ifdef NETCDF_ENABLE_CDF5
2110 cdf5built = 1;
2111#endif
2112#ifdef NETCDF_ENABLE_NCZARR
2113 nczarrbuilt = 1;
2114#endif
2115 /* Check which UDF formats are built (i.e., have been registered).
2116 * A UDF format is considered "built" if its dispatch table is non-NULL. */
2117 int udfbuilt[NC_MAX_UDF_FORMATS] = {0};
2118 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2119 if(UDF_dispatch_tables[i] != NULL)
2120 udfbuilt[i] = 1;
2121 }
2122
2123 if(!hdf5built && model.impl == NC_FORMATX_NC4)
2124 {stat = NC_ENOTBUILT; goto done;}
2125 if(!hdf4built && model.impl == NC_FORMATX_NC_HDF4)
2126 {stat = NC_ENOTBUILT; goto done;}
2127 if(!cdf5built && model.impl == NC_FORMATX_NC3 && model.format == NC_FORMAT_CDF5)
2128 {stat = NC_ENOTBUILT; goto done;}
2129 if(!nczarrbuilt && model.impl == NC_FORMATX_NCZARR)
2130 {stat = NC_ENOTBUILT; goto done;}
2131 /* Check all UDF formats - ensure the requested format has been registered */
2132 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2133 /* Convert array index to format constant (handles gap: UDF0=8, UDF1=9, UDF2=11...) */
2134 int formatx = (i <= 1) ? (NC_FORMATX_UDF0 + i) : (NC_FORMATX_UDF2 + i - 2);
2135 if(!udfbuilt[i] && model.impl == formatx)
2136 {stat = NC_ENOTBUILT; goto done;}
2137 }
2138 }
2139#else
2140 {
2141 unsigned built = 0 /* leave off the trailing semicolon so we can build constant */
2142 | (1<<NC_FORMATX_NC3) /* NC3 always supported */
2143#ifdef USE_HDF5
2144 | (1<<NC_FORMATX_NC_HDF5)
2145#endif
2146#ifdef USE_HDF4
2147 | (1<<NC_FORMATX_NC_HDF4)
2148#endif
2149#ifdef NETCDF_ENABLE_NCZARR
2150 | (1<<NC_FORMATX_NCZARR)
2151#endif
2152#ifdef NETCDF_ENABLE_DAP
2153 | (1<<NC_FORMATX_DAP2)
2154#endif
2155#ifdef NETCDF_ENABLE_DAP4
2156 | (1<<NC_FORMATX_DAP4)
2157#endif
2158#ifdef USE_PNETCDF
2159 | (1<<NC_FORMATX_PNETCDF)
2160#endif
2161 ; /* end of the built flags */
2162 /* Add UDF formats to built flags - set bit for each registered UDF format.
2163 * Use unsigned literal (1U) to avoid integer overflow for higher bit positions. */
2164 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2165 if(UDF_dispatch_tables[i] != NULL) {
2166 /* Convert array index to format constant */
2167 int formatx = (i <= 1) ? (NC_FORMATX_UDF0 + i) : (NC_FORMATX_UDF2 + i - 2);
2168 built |= (1U << formatx);
2169 }
2170 }
2171 /* Verify the requested format is available */
2172 if((built & (1U << model.impl)) == 0)
2173 {stat = NC_ENOTBUILT; goto done;}
2174#ifndef NETCDF_ENABLE_CDF5
2175 /* Special case because there is no separate CDF5 dispatcher */
2176 if(model.impl == NC_FORMATX_NC3 && (omode & NC_64BIT_DATA))
2177 {stat = NC_ENOTBUILT; goto done;}
2178#endif
2179 }
2180#endif
2181 /* Figure out what dispatcher to use */
2182 if (!dispatcher) {
2183 switch (model.impl) {
2184#ifdef NETCDF_ENABLE_DAP
2185 case NC_FORMATX_DAP2:
2186 dispatcher = NCD2_dispatch_table;
2187 break;
2188#endif
2189#ifdef NETCDF_ENABLE_DAP4
2190 case NC_FORMATX_DAP4:
2191 dispatcher = NCD4_dispatch_table;
2192 break;
2193#endif
2194#ifdef NETCDF_ENABLE_NCZARR
2195 case NC_FORMATX_NCZARR:
2196 dispatcher = NCZ_dispatch_table;
2197 break;
2198#endif
2199#ifdef USE_PNETCDF
2200 case NC_FORMATX_PNETCDF:
2201 dispatcher = NCP_dispatch_table;
2202 break;
2203#endif
2204#ifdef USE_HDF5
2205 case NC_FORMATX_NC4:
2206 dispatcher = HDF5_dispatch_table;
2207 break;
2208#endif
2209#ifdef USE_HDF4
2210 case NC_FORMATX_NC_HDF4:
2211 dispatcher = HDF4_dispatch_table;
2212 break;
2213#endif
2214#ifdef USE_NETCDF4
2215 case NC_FORMATX_UDF0:
2216 case NC_FORMATX_UDF1:
2217 case NC_FORMATX_UDF2:
2218 case NC_FORMATX_UDF3:
2219 case NC_FORMATX_UDF4:
2220 case NC_FORMATX_UDF5:
2221 case NC_FORMATX_UDF6:
2222 case NC_FORMATX_UDF7:
2223 case NC_FORMATX_UDF8:
2224 case NC_FORMATX_UDF9:
2225 {
2226 /* Convert format constant to array index and validate */
2227 int udf_index = udf_formatx_to_index(model.impl);
2228 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS) {
2229 stat = NC_EINVAL;
2230 goto done;
2231 }
2232 /* Get the dispatch table for this UDF slot */
2233 dispatcher = UDF_dispatch_tables[udf_index];
2234 /* Ensure the UDF format has been registered via nc_def_user_format() */
2235 if (!dispatcher) {
2236 stat = NC_ENOTBUILT;
2237 goto done;
2238 }
2239 }
2240 break;
2241#endif /* USE_NETCDF4 */
2242 case NC_FORMATX_NC3:
2243 dispatcher = NC3_dispatch_table;
2244 break;
2245 default:
2246 stat = NC_ENOTNC;
2247 goto done;
2248 }
2249 }
2250
2251
2252 /* If we can't figure out what dispatch table to use, give up. */
2253 if (!dispatcher) {stat = NC_ENOTNC; goto done;}
2254
2255 /* Create the NC* instance and insert its dispatcher */
2256 if((stat = new_NC(dispatcher,path,omode,&ncp))) goto done;
2257
2258 /* Add to list of known open files. This assigns an ext_ncid. */
2259 add_to_NCList(ncp);
2260
2261 /* Assume open will fill in remaining ncp fields */
2262 stat = dispatcher->open(ncp->path, omode, basepe, chunksizehintp,
2263 parameters, dispatcher, ncp->ext_ncid);
2264 if(stat == NC_NOERR) {
2265 if(ncidp) *ncidp = ncp->ext_ncid;
2266 } else {
2267 del_from_NCList(ncp);
2268 free_NC(ncp);
2269 }
2270
2271done:
2272 nullfree(path);
2273 nullfree(newpath);
2274 return stat;
2275}
2276
2277/*Provide an internal function for generating pseudo file descriptors
2278 for systems that are not file based (e.g. dap, memio).
2279*/
2280
2282static int pseudofd = 0;
2283
2291int
2292nc__pseudofd(void)
2293{
2294 if(pseudofd == 0) {
2295#ifdef HAVE_GETRLIMIT
2296 int maxfd = 32767; /* default */
2297 struct rlimit rl;
2298 if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
2299 if(rl.rlim_max != RLIM_INFINITY)
2300 maxfd = (int)rl.rlim_max;
2301 if(rl.rlim_cur != RLIM_INFINITY)
2302 maxfd = (int)rl.rlim_cur;
2303 }
2304 pseudofd = maxfd+1;
2305#endif
2306 }
2307 return pseudofd++;
2308}
int nc_inq_nvars(int ncid, int *nvarsp)
Learn the number of variables in a file or group.
Definition dfile.c:1688
static int udf_mode_to_index(int mode_flag)
Helper function to convert NC_UDFn mode flag to array index (0-9).
Definition dfile.c:59
static int udf_formatx_to_index(int formatx)
Helper function to convert NC_FORMATX_UDFn to array index (0-9).
Definition dfile.c:87
int nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
Inquire about user-defined format.
Definition dfile.c:220
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:504
int nc_close(int ncid)
Close an open netCDF dataset.
Definition dfile.c:1334
int nc_abort(int ncid)
No longer necessary for user to invoke manually.
Definition dfile.c:1281
int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
Definition dfile.c:432
int nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
Inquire about a file or group.
Definition dfile.c:1669
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:1616
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:1393
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:1152
int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
Definition dfile.c:1508
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:550
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:755
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's file.
Definition dfile.c:932
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:810
int nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number)
Add handling of user-defined format.
Definition dfile.c:166
int nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
Inquire about a type.
Definition dfile.c:1762
int nc_enddef(int ncid)
Leave define mode.
Definition dfile.c:1061
int nc_redef(int ncid)
Put open netcdf dataset into define mode.
Definition dfile.c:997
int nc_open(const char *path, int omode, int *ncidp)
Open an existing netCDF file.
Definition dfile.c:698
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:875
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:1581
int nc_sync(int ncid)
Synchronize an open netcdf dataset to disk.
Definition dfile.c:1229
static int check_create_mode(int mode)
Check the create mode parameter for sanity.
Definition dfile.c:1809
#define NC_MAX_MAGIC_NUMBER_LEN
Max len of user-defined format magic number.
Definition netcdf.h:195
#define NC_NETCDF4
Use netCDF-4/HDF5 format.
Definition netcdf.h:179
#define NC_FORMATX_UDF4
User-defined format 4.
Definition netcdf.h:267
#define NC_UDF0
User-defined format 0 (bit 6).
Definition netcdf.h:152
#define NC_EDISKLESS
Error in using diskless access.
Definition netcdf.h:558
#define NC_SIZEHINT_DEFAULT
Let nc__create() or nc__open() figure out a suitable buffer size.
Definition netcdf.h:294
#define NC_EBADTYPE
Not a netcdf data type.
Definition netcdf.h:459
#define NC_MMAP
Definition netcdf.h:141
#define NC_INMEMORY
Read from memory.
Definition netcdf.h:189
#define NC_CDF5
Alias NC_CDF5 to NC_64BIT_DATA.
Definition netcdf.h:144
#define NC_FORMATX_UDF7
User-defined format 7.
Definition netcdf.h:270
#define NC_FORMATX_NC3
Extended format specifier returned by nc_inq_format_extended() Added in version 4....
Definition netcdf.h:246
#define NC_FORMATX_NCZARR
Added in version 4.8.0.
Definition netcdf.h:262
#define NC_ENOTNC
Not a netcdf file.
Definition netcdf.h:473
struct NC_Dispatch NC_Dispatch
Register a user-defined format.
Definition netcdf.h:652
#define NC_UDF9
User-defined format 9 (bit 25).
Definition netcdf.h:163
#define NC_NAT
Not A Type.
Definition netcdf.h:34
#define NC_UDF8
User-defined format 8 (bit 24).
Definition netcdf.h:162
#define NC_64BIT_OFFSET
Use large (64-bit) file offsets.
Definition netcdf.h:167
#define NC_UDF5
User-defined format 5 (bit 21).
Definition netcdf.h:159
#define NC_EINMEMORY
In-memory file error.
Definition netcdf.h:565
#define NC_FORMATX_UDF1
User-defined format 1.
Definition netcdf.h:260
#define NC_FORMATX_PNETCDF
Extended format specifier returned by nc_inq_format_extended() Added in version 4....
Definition netcdf.h:250
#define NC_FORMATX_UDF2
User-defined format 2.
Definition netcdf.h:265
#define NC_FORMAT_CDF5
Format specifier for nc_set_default_format() and returned by nc_inq_format.
Definition netcdf.h:221
#define NC_UDF3
User-defined format 3 (bit 19).
Definition netcdf.h:157
#define NC_FORMATX_UDF5
User-defined format 5.
Definition netcdf.h:268
#define NC_UDF6
User-defined format 6 (bit 22).
Definition netcdf.h:160
#define NC_UDF2
User-defined format 2 (bit 16).
Definition netcdf.h:156
#define NC_FORMATX_NC_HDF4
netCDF-4 subset of HDF4
Definition netcdf.h:249
#define NC_WRITE
Set read-write access for nc_open().
Definition netcdf.h:136
#define NC_FORMATX_NC_HDF5
netCDF-4 subset of HDF5
Definition netcdf.h:247
#define NC_FORMATX_DAP4
Extended format specifier returned by nc_inq_format_extended() Added in version 4....
Definition netcdf.h:252
#define NC_FORMATX_UDF8
User-defined format 8.
Definition netcdf.h:271
#define NC_FORMATX_UDF0
User-defined format 0.
Definition netcdf.h:259
#define NC_FORMATX_UDF3
User-defined format 3.
Definition netcdf.h:266
#define NC_UDF7
User-defined format 7 (bit 23).
Definition netcdf.h:161
#define NC_DISKLESS
Use diskless file.
Definition netcdf.h:140
#define NC_FORMATX_DAP2
Extended format specifier returned by nc_inq_format_extended() Added in version 4....
Definition netcdf.h:251
#define NC_EINVAL
Invalid Argument.
Definition netcdf.h:427
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition netcdf.h:166
#define NC_MAX_NAME
Maximum for classic library.
Definition netcdf.h:330
#define NC_NOERR
No Error.
Definition netcdf.h:417
#define NC_64BIT_DATA
CDF-5 format: classic model but 64 bit dimensions and sizes.
Definition netcdf.h:143
#define NC_ENOTBUILT
Attempt to use feature that was not turned on when netCDF was built.
Definition netcdf.h:557
#define NC_UDF1
User-defined format 1 (bit 7).
Definition netcdf.h:153
#define NC_MAX_UDF_FORMATS
Maximum number of user-defined format slots (UDF0-UDF9).
Definition netcdf.h:199
#define NC_FORMATX_UDF9
User-defined format 9.
Definition netcdf.h:272
#define NC_UDF4
User-defined format 4 (bit 20).
Definition netcdf.h:158
#define NC_FORMATX_UDF6
User-defined format 6.
Definition netcdf.h:269
int nc_type
The nc_type type is just an int.
Definition netcdf.h:25
#define NC_FORMATX_NC4
alias
Definition netcdf.h:248
Main header file for in-memory (diskless) functionality.