NetCDF 4.10.1
Loading...
Searching...
No Matches
dfile.c
Go to the documentation of this file.
1
12
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
135
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
215int
216nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
217{
218 int udf_index;
219
220 /* Get the UDF index from the mode flag. */
221 udf_index = udf_mode_to_index(mode_flag);
222 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS)
223 return NC_EINVAL;
224
225 /* Return the dispatch table and magic number. */
226 if (dispatch_table)
227 *dispatch_table = UDF_dispatch_tables[udf_index];
228 if (magic_number)
229 strncpy(magic_number, UDF_magic_numbers[udf_index], NC_MAX_MAGIC_NUMBER_LEN);
230
231 return NC_NOERR;
232}
233
427int
428nc_create(const char *path, int cmode, int *ncidp)
429{
430 return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
431}
432
499int
500nc__create(const char *path, int cmode, size_t initialsz,
501 size_t *chunksizehintp, int *ncidp)
502{
503 return NC_create(path, cmode, initialsz, 0,
504 chunksizehintp, 0, NULL, ncidp);
505}
506
544
545int
546nc_create_mem(const char* path, int mode, size_t initialsize, int* ncidp)
547{
548 if(mode & NC_MMAP) return NC_EINVAL;
549 mode |= NC_INMEMORY; /* Specifically, do not set NC_DISKLESS */
550 return NC_create(path, mode, initialsize, 0, NULL, 0, NULL, ncidp);
551}
552
572int
573nc__create_mp(const char *path, int cmode, size_t initialsz,
574 int basepe, size_t *chunksizehintp, int *ncidp)
575{
576 return NC_create(path, cmode, initialsz, basepe,
577 chunksizehintp, 0, NULL, ncidp);
578}
579
693int
694nc_open(const char *path, int omode, int *ncidp)
695{
696 return NC_open(path, omode, 0, NULL, 0, NULL, ncidp);
697}
698
750int
751nc__open(const char *path, int omode,
752 size_t *chunksizehintp, int *ncidp)
753{
754 /* this API is for non-parallel access.
755 * Note nc_open_par() also calls NC_open().
756 */
757 return NC_open(path, omode, 0, chunksizehintp, 0, NULL, ncidp);
758}
759
805int
806nc_open_mem(const char* path, int omode, size_t size, void* memory, int* ncidp)
807{
808 NC_memio meminfo;
809
810 /* Sanity checks */
811 if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL)
812 return NC_EINVAL;
813 if(omode & (NC_WRITE|NC_MMAP))
814 return NC_EINVAL;
815 omode |= (NC_INMEMORY); /* Note: NC_INMEMORY and NC_DISKLESS are mutually exclusive*/
816 meminfo.size = size;
817 meminfo.memory = memory;
818 meminfo.flags = NC_MEMIO_LOCKED;
819 return NC_open(path, omode, 0, NULL, 0, &meminfo, ncidp);
820}
821
870int
871nc_open_memio(const char* path, int omode, NC_memio* params, int* ncidp)
872{
873 /* Sanity checks */
874 if(path == NULL || params == NULL)
875 return NC_EINVAL;
876 if(params->memory == NULL || params->size < MAGIC_NUMBER_LEN)
877 return NC_EINVAL;
878
879 if(omode & NC_MMAP)
880 return NC_EINVAL;
881 omode |= (NC_INMEMORY);
882 return NC_open(path, omode, 0, NULL, 0, params, ncidp);
883}
884
903int
904nc__open_mp(const char *path, int omode, int basepe,
905 size_t *chunksizehintp, int *ncidp)
906{
907 return NC_open(path, omode, basepe, chunksizehintp, 0, NULL, ncidp);
908}
909
927int
928nc_inq_path(int ncid, size_t *pathlen, char *path)
929{
930 NC* ncp;
931 int stat = NC_NOERR;
932 if ((stat = NC_check_id(ncid, &ncp)))
933 return stat;
934 if(ncp->path == NULL) {
935 if(pathlen) *pathlen = 0;
936 if(path) path[0] = '\0';
937 } else {
938 if (pathlen) *pathlen = strlen(ncp->path);
939 if (path) strcpy(path, ncp->path);
940 }
941 return stat;
942}
943
992int
993nc_redef(int ncid)
994{
995 NC* ncp;
996 int stat = NC_check_id(ncid, &ncp);
997 if(stat != NC_NOERR) return stat;
998 return ncp->dispatch->redef(ncid);
999}
1000
1056int
1057nc_enddef(int ncid)
1058{
1059 int status = NC_NOERR;
1060 NC *ncp;
1061 status = NC_check_id(ncid, &ncp);
1062 if(status != NC_NOERR) return status;
1063 return ncp->dispatch->_enddef(ncid,0,1,0,1);
1064}
1065
1147int
1148nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree,
1149 size_t r_align)
1150{
1151 NC* ncp;
1152 int stat = NC_check_id(ncid, &ncp);
1153 if(stat != NC_NOERR) return stat;
1154 return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
1155}
1156
1224int
1225nc_sync(int ncid)
1226{
1227 NC* ncp;
1228 int stat = NC_check_id(ncid, &ncp);
1229 if(stat != NC_NOERR) return stat;
1230 return ncp->dispatch->sync(ncid);
1231}
1232
1276int
1277nc_abort(int ncid)
1278{
1279 NC* ncp;
1280 int stat = NC_check_id(ncid, &ncp);
1281 if(stat != NC_NOERR) return stat;
1282
1283 stat = ncp->dispatch->abort(ncid);
1284 del_from_NCList(ncp);
1285 free_NC(ncp);
1286 return stat;
1287}
1288
1329int
1330nc_close(int ncid)
1331{
1332 NC* ncp;
1333 int stat = NC_check_id(ncid, &ncp);
1334 if(stat != NC_NOERR) return stat;
1335
1336 stat = ncp->dispatch->close(ncid,NULL);
1337 /* Remove from the nc list */
1338 if (!stat)
1339 {
1340 del_from_NCList(ncp);
1341 free_NC(ncp);
1342 }
1343 return stat;
1344}
1345
1388int
1389nc_close_memio(int ncid, NC_memio* memio)
1390{
1391 NC* ncp;
1392 int stat = NC_check_id(ncid, &ncp);
1393 if(stat != NC_NOERR) return stat;
1394
1395 stat = ncp->dispatch->close(ncid,memio);
1396 /* Remove from the nc list */
1397 if (!stat)
1398 {
1399 del_from_NCList(ncp);
1400 free_NC(ncp);
1401 }
1402 return stat;
1403}
1404
1503int
1504nc_set_fill(int ncid, int fillmode, int *old_modep)
1505{
1506 NC* ncp;
1507 int stat = NC_check_id(ncid, &ncp);
1508 if(stat != NC_NOERR) return stat;
1509 return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1510}
1511
1526int
1527nc_inq_base_pe(int ncid, int *pe)
1528{
1529 NC* ncp;
1530 int stat = NC_check_id(ncid, &ncp);
1531 if(stat != NC_NOERR) return stat;
1532 if (pe) *pe = 0;
1533 return NC_NOERR;
1534}
1535
1550int
1551nc_set_base_pe(int ncid, int pe)
1552{
1553 NC* ncp;
1554 int stat = NC_check_id(ncid, &ncp);
1555 if(stat != NC_NOERR) return stat;
1556 return NC_NOERR;
1557}
1558
1576int
1577nc_inq_format(int ncid, int *formatp)
1578{
1579 NC* ncp;
1580 int stat = NC_check_id(ncid, &ncp);
1581 if(stat != NC_NOERR) return stat;
1582 return ncp->dispatch->inq_format(ncid,formatp);
1583}
1584
1611int
1612nc_inq_format_extended(int ncid, int *formatp, int *modep)
1613{
1614 NC* ncp;
1615 int stat = NC_check_id(ncid, &ncp);
1616 if(stat != NC_NOERR) return stat;
1617 return ncp->dispatch->inq_format_extended(ncid,formatp,modep);
1618}
1619
1664int
1665nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1666{
1667 NC* ncp;
1668 int stat = NC_check_id(ncid, &ncp);
1669 if(stat != NC_NOERR) return stat;
1670 return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1671}
1672
1683int
1684nc_inq_nvars(int ncid, int *nvarsp)
1685{
1686 NC* ncp;
1687 int stat = NC_check_id(ncid, &ncp);
1688 if(stat != NC_NOERR) return stat;
1689 return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1690}
1691
1757int
1758nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1759{
1760 NC* ncp;
1761 int stat;
1762
1763 /* Do a quick triage on xtype */
1764 if(xtype <= NC_NAT) return NC_EBADTYPE;
1765 /* For compatibility, we need to allow inq about
1766 atomic types, even if ncid is ill-defined */
1767 if(xtype <= ATOMICTYPEMAX4) {
1768 if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1769 if(size) *size = NC_atomictypelen(xtype);
1770 return NC_NOERR;
1771 }
1772 /* Apparently asking about a user defined type, so we need
1773 a valid ncid */
1774 stat = NC_check_id(ncid, &ncp);
1775 if(stat != NC_NOERR) /* bad ncid */
1776 return NC_EBADTYPE;
1777 /* have good ncid */
1778 return ncp->dispatch->inq_type(ncid,xtype,name,size);
1779}
1780
1786
1787
1804static int
1806{
1807 int mode_format;
1808 int use_mmap = 0;
1809 int inmemory = 0;
1810 int diskless = 0;
1811
1812 /* This is a clever check to see if more than one format bit is
1813 * set. */
1814 mode_format = (mode & NC_NETCDF4) | (mode & NC_64BIT_OFFSET) |
1815 (mode & NC_CDF5);
1816 if (mode_format && (mode_format & (mode_format - 1)))
1817 return NC_EINVAL;
1818
1819 use_mmap = ((mode & NC_MMAP) == NC_MMAP);
1820 inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY);
1821 diskless = ((mode & NC_DISKLESS) == NC_DISKLESS);
1822
1823 /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
1824 if(diskless && inmemory) return NC_EDISKLESS;
1825 if(diskless && use_mmap) return NC_EDISKLESS;
1826 if(inmemory && use_mmap) return NC_EINMEMORY;
1827
1828 /* mmap is not allowed for netcdf-4 */
1829 if(use_mmap && (mode & NC_NETCDF4)) return NC_EINVAL;
1830
1831#ifndef USE_NETCDF4
1832 /* If the user asks for a netCDF-4 file, and the library was built
1833 * without netCDF-4, then return an error.*/
1834 if (mode & NC_NETCDF4)
1835 return NC_ENOTBUILT;
1836#endif /* USE_NETCDF4 undefined */
1837
1838 /* Well I guess there is some sanity in the world after all. */
1839 return NC_NOERR;
1840}
1841
1869int
1870NC_create(const char *path0, int cmode, size_t initialsz,
1871 int basepe, size_t *chunksizehintp, int useparallel,
1872 void* parameters, int *ncidp)
1873{
1874 int stat = NC_NOERR;
1875 NC* ncp = NULL;
1876 const NC_Dispatch* dispatcher = NULL;
1877 char* path = NULL;
1878 NCmodel model;
1879 char* newpath = NULL;
1880
1881 TRACE(nc_create);
1882 if(path0 == NULL)
1883 {stat = NC_EINVAL; goto done;}
1884
1885 /* Check mode flag for sanity. */
1886 if ((stat = check_create_mode(cmode))) goto done;
1887
1888 /* Initialize the library. The available dispatch tables
1889 * will depend on how netCDF was built
1890 * (with/without netCDF-4, DAP, CDMREMOTE). */
1891 if(!NC_initialized) {
1892 if ((stat = nc_initialize())) goto done;
1893 }
1894
1895 {
1896 /* Skip past any leading whitespace in path */
1897 const unsigned char* p;
1898 for(p=(const unsigned char*)path0;*p;p++) {if(*p > ' ') break;}
1899 path = nulldup((const char*)p);
1900 }
1901
1902 memset(&model,0,sizeof(model));
1903 newpath = NULL;
1904 if((stat = NC_infermodel(path,&cmode,1,useparallel,NULL,&model,&newpath))) goto done;
1905 if(newpath) {
1906 nullfree(path);
1907 path = newpath;
1908 newpath = NULL;
1909 }
1910
1911 assert(model.format != 0 && model.impl != 0);
1912
1913 /* Now, check for NC_ENOTBUILT cases limited to create (so e.g. HDF4 is not listed) */
1914#ifndef USE_HDF5
1915 if (model.impl == NC_FORMATX_NC4)
1916 {stat = NC_ENOTBUILT; goto done;}
1917#endif
1918#ifndef USE_PNETCDF
1919 if (model.impl == NC_FORMATX_PNETCDF)
1920 {stat = NC_ENOTBUILT; goto done;}
1921#endif
1922#ifndef NETCDF_ENABLE_CDF5
1923 if (model.impl == NC_FORMATX_NC3 && (cmode & NC_64BIT_DATA))
1924 {stat = NC_ENOTBUILT; goto done;}
1925#endif
1926
1927 /* Figure out what dispatcher to use */
1928 switch (model.impl) {
1929#ifdef USE_HDF5
1930 case NC_FORMATX_NC4:
1931 dispatcher = HDF5_dispatch_table;
1932 break;
1933#endif
1934#ifdef USE_PNETCDF
1935 case NC_FORMATX_PNETCDF:
1936 dispatcher = NCP_dispatch_table;
1937 break;
1938#endif
1939#ifdef USE_NETCDF4
1940 case NC_FORMATX_UDF0:
1941 case NC_FORMATX_UDF1:
1942 case NC_FORMATX_UDF2:
1943 case NC_FORMATX_UDF3:
1944 case NC_FORMATX_UDF4:
1945 case NC_FORMATX_UDF5:
1946 case NC_FORMATX_UDF6:
1947 case NC_FORMATX_UDF7:
1948 case NC_FORMATX_UDF8:
1949 case NC_FORMATX_UDF9:
1950 {
1951 /* Convert format constant to array index and validate */
1952 int udf_index = udf_formatx_to_index(model.impl);
1953 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS) {
1954 stat = NC_EINVAL;
1955 goto done;
1956 }
1957 /* Get the dispatch table for this UDF slot */
1958 dispatcher = UDF_dispatch_tables[udf_index];
1959 /* Ensure the UDF format has been registered via nc_def_user_format() */
1960 if (!dispatcher) {
1961 stat = NC_ENOTBUILT;
1962 goto done;
1963 }
1964 }
1965 break;
1966#endif /* USE_NETCDF4 */
1967#ifdef NETCDF_ENABLE_NCZARR
1968 case NC_FORMATX_NCZARR:
1969 dispatcher = NCZ_dispatch_table;
1970 break;
1971#endif
1972 case NC_FORMATX_NC3:
1973 dispatcher = NC3_dispatch_table;
1974 break;
1975 default:
1976 {stat = NC_ENOTNC; goto done;}
1977 }
1978
1979 /* Create the NC* instance and insert its dispatcher and model */
1980 if((stat = new_NC(dispatcher,path,cmode,&ncp))) goto done;
1981
1982 /* Add to list of known open files and define ext_ncid */
1983 add_to_NCList(ncp);
1984
1985 /* Assume create will fill in remaining ncp fields */
1986 if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp,
1987 parameters, dispatcher, ncp->ext_ncid))) {
1988 del_from_NCList(ncp); /* oh well */
1989 free_NC(ncp);
1990 } else {
1991 if(ncidp)*ncidp = ncp->ext_ncid;
1992 }
1993done:
1994 nullfree(path);
1995 nullfree(newpath);
1996 return stat;
1997}
1998
2022int
2023NC_open(const char *path0, int omode, int basepe, size_t *chunksizehintp,
2024 int useparallel, void* parameters, int *ncidp)
2025{
2026 int stat = NC_NOERR;
2027 NC* ncp = NULL;
2028 const NC_Dispatch* dispatcher = NULL;
2029 int inmemory = 0;
2030 int diskless = 0;
2031 int use_mmap = 0;
2032 char* path = NULL;
2033 NCmodel model;
2034 char* newpath = NULL;
2035
2036 TRACE(nc_open);
2037 if(!NC_initialized) {
2038 stat = nc_initialize();
2039 if(stat) goto done;
2040 }
2041
2042 /* Check inputs. */
2043 if (!path0)
2044 {stat = NC_EINVAL; goto done;}
2045
2046 /* Capture the inmemory related flags */
2047 use_mmap = ((omode & NC_MMAP) == NC_MMAP);
2048 diskless = ((omode & NC_DISKLESS) == NC_DISKLESS);
2049 inmemory = ((omode & NC_INMEMORY) == NC_INMEMORY);
2050
2051 /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */
2052 if(diskless && inmemory) {stat = NC_EDISKLESS; goto done;}
2053 if(diskless && use_mmap) {stat = NC_EDISKLESS; goto done;}
2054 if(inmemory && use_mmap) {stat = NC_EINMEMORY; goto done;}
2055
2056 /* mmap is not allowed for netcdf-4 */
2057 if(use_mmap && (omode & NC_NETCDF4)) {stat = NC_EINVAL; goto done;}
2058
2059 /* Attempt to do file path conversion: note that this will do
2060 nothing if path is a 'file:...' url, so it will need to be
2061 repeated in protocol code (e.g. libdap2, libdap4, etc).
2062 */
2063
2064 {
2065 /* Skip past any leading whitespace in path */
2066 const char* p;
2067 for(p=(const char*)path0;*p;p++) {if(*p < 0 || *p > ' ') break;}
2068 path = nulldup(p);
2069 }
2070
2071 memset(&model,0,sizeof(model));
2072 /* Infer model implementation and format, possibly by reading the file */
2073 if((stat = NC_infermodel(path,&omode,0,useparallel,parameters,&model,&newpath)))
2074 goto done;
2075 if(newpath) {
2076 nullfree(path);
2077 path = newpath;
2078 newpath = NULL;
2079 }
2080
2081 /* Still no implementation, give up */
2082 if(model.impl == 0) {
2083#ifdef DEBUG
2084 fprintf(stderr,"implementation == 0\n");
2085#endif
2086 {stat = NC_ENOTNC; goto done;}
2087 }
2088
2089 /* Suppress unsupported formats */
2090#if 0
2091 /* (should be more compact, table-driven, way to do this) */
2092 {
2093 int hdf5built = 0;
2094 int hdf4built = 0;
2095 int cdf5built = 0;
2096 int udf0built = 0;
2097 int udf1built = 0;
2098 int nczarrbuilt = 0;
2099#ifdef USE_NETCDF4
2100 hdf5built = 1;
2101#endif
2102#ifdef USE_HDF4
2103 hdf4built = 1;
2104#endif
2105#ifdef NETCDF_ENABLE_CDF5
2106 cdf5built = 1;
2107#endif
2108#ifdef NETCDF_ENABLE_NCZARR
2109 nczarrbuilt = 1;
2110#endif
2111 /* Check which UDF formats are built (i.e., have been registered).
2112 * A UDF format is considered "built" if its dispatch table is non-NULL. */
2113 int udfbuilt[NC_MAX_UDF_FORMATS] = {0};
2114 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2115 if(UDF_dispatch_tables[i] != NULL)
2116 udfbuilt[i] = 1;
2117 }
2118
2119 if(!hdf5built && model.impl == NC_FORMATX_NC4)
2120 {stat = NC_ENOTBUILT; goto done;}
2121 if(!hdf4built && model.impl == NC_FORMATX_NC_HDF4)
2122 {stat = NC_ENOTBUILT; goto done;}
2123 if(!cdf5built && model.impl == NC_FORMATX_NC3 && model.format == NC_FORMAT_CDF5)
2124 {stat = NC_ENOTBUILT; goto done;}
2125 if(!nczarrbuilt && model.impl == NC_FORMATX_NCZARR)
2126 {stat = NC_ENOTBUILT; goto done;}
2127 /* Check all UDF formats - ensure the requested format has been registered */
2128 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2129 /* Convert array index to format constant (handles gap: UDF0=8, UDF1=9, UDF2=11...) */
2130 int formatx = (i <= 1) ? (NC_FORMATX_UDF0 + i) : (NC_FORMATX_UDF2 + i - 2);
2131 if(!udfbuilt[i] && model.impl == formatx)
2132 {stat = NC_ENOTBUILT; goto done;}
2133 }
2134 }
2135#else
2136 {
2137 unsigned built = 0 /* leave off the trailing semicolon so we can build constant */
2138 | (1<<NC_FORMATX_NC3) /* NC3 always supported */
2139#ifdef USE_HDF5
2140 | (1<<NC_FORMATX_NC_HDF5)
2141#endif
2142#ifdef USE_HDF4
2143 | (1<<NC_FORMATX_NC_HDF4)
2144#endif
2145#ifdef NETCDF_ENABLE_NCZARR
2146 | (1<<NC_FORMATX_NCZARR)
2147#endif
2148#ifdef NETCDF_ENABLE_DAP
2149 | (1<<NC_FORMATX_DAP2)
2150#endif
2151#ifdef NETCDF_ENABLE_DAP4
2152 | (1<<NC_FORMATX_DAP4)
2153#endif
2154#ifdef USE_PNETCDF
2155 | (1<<NC_FORMATX_PNETCDF)
2156#endif
2157 ; /* end of the built flags */
2158 /* Add UDF formats to built flags - set bit for each registered UDF format.
2159 * Use unsigned literal (1U) to avoid integer overflow for higher bit positions. */
2160 for(int i = 0; i < NC_MAX_UDF_FORMATS; i++) {
2161 if(UDF_dispatch_tables[i] != NULL) {
2162 /* Convert array index to format constant */
2163 int formatx = (i <= 1) ? (NC_FORMATX_UDF0 + i) : (NC_FORMATX_UDF2 + i - 2);
2164 built |= (1U << formatx);
2165 }
2166 }
2167 /* Verify the requested format is available */
2168 if((built & (1U << model.impl)) == 0)
2169 {stat = NC_ENOTBUILT; goto done;}
2170#ifndef NETCDF_ENABLE_CDF5
2171 /* Special case because there is no separate CDF5 dispatcher */
2172 if(model.impl == NC_FORMATX_NC3 && (omode & NC_64BIT_DATA))
2173 {stat = NC_ENOTBUILT; goto done;}
2174#endif
2175 }
2176#endif
2177 /* Figure out what dispatcher to use */
2178 if (!dispatcher) {
2179 switch (model.impl) {
2180#ifdef NETCDF_ENABLE_DAP
2181 case NC_FORMATX_DAP2:
2182 dispatcher = NCD2_dispatch_table;
2183 break;
2184#endif
2185#ifdef NETCDF_ENABLE_DAP4
2186 case NC_FORMATX_DAP4:
2187 dispatcher = NCD4_dispatch_table;
2188 break;
2189#endif
2190#ifdef NETCDF_ENABLE_NCZARR
2191 case NC_FORMATX_NCZARR:
2192 dispatcher = NCZ_dispatch_table;
2193 break;
2194#endif
2195#ifdef USE_PNETCDF
2196 case NC_FORMATX_PNETCDF:
2197 dispatcher = NCP_dispatch_table;
2198 break;
2199#endif
2200#ifdef USE_HDF5
2201 case NC_FORMATX_NC4:
2202 dispatcher = HDF5_dispatch_table;
2203 break;
2204#endif
2205#ifdef USE_HDF4
2206 case NC_FORMATX_NC_HDF4:
2207 dispatcher = HDF4_dispatch_table;
2208 break;
2209#endif
2210#ifdef USE_NETCDF4
2211 case NC_FORMATX_UDF0:
2212 case NC_FORMATX_UDF1:
2213 case NC_FORMATX_UDF2:
2214 case NC_FORMATX_UDF3:
2215 case NC_FORMATX_UDF4:
2216 case NC_FORMATX_UDF5:
2217 case NC_FORMATX_UDF6:
2218 case NC_FORMATX_UDF7:
2219 case NC_FORMATX_UDF8:
2220 case NC_FORMATX_UDF9:
2221 {
2222 /* Convert format constant to array index and validate */
2223 int udf_index = udf_formatx_to_index(model.impl);
2224 if (udf_index < 0 || udf_index >= NC_MAX_UDF_FORMATS) {
2225 stat = NC_EINVAL;
2226 goto done;
2227 }
2228 /* Get the dispatch table for this UDF slot */
2229 dispatcher = UDF_dispatch_tables[udf_index];
2230 /* Ensure the UDF format has been registered via nc_def_user_format() */
2231 if (!dispatcher) {
2232 stat = NC_ENOTBUILT;
2233 goto done;
2234 }
2235 }
2236 break;
2237#endif /* USE_NETCDF4 */
2238 case NC_FORMATX_NC3:
2239 dispatcher = NC3_dispatch_table;
2240 break;
2241 default:
2242 stat = NC_ENOTNC;
2243 goto done;
2244 }
2245 }
2246
2247
2248 /* If we can't figure out what dispatch table to use, give up. */
2249 if (!dispatcher) {stat = NC_ENOTNC; goto done;}
2250
2251 /* Create the NC* instance and insert its dispatcher */
2252 if((stat = new_NC(dispatcher,path,omode,&ncp))) goto done;
2253
2254 /* Add to list of known open files. This assigns an ext_ncid. */
2255 add_to_NCList(ncp);
2256
2257 /* Assume open will fill in remaining ncp fields */
2258 stat = dispatcher->open(ncp->path, omode, basepe, chunksizehintp,
2259 parameters, dispatcher, ncp->ext_ncid);
2260 if(stat == NC_NOERR) {
2261 if(ncidp) *ncidp = ncp->ext_ncid;
2262 } else {
2263 del_from_NCList(ncp);
2264 free_NC(ncp);
2265 }
2266
2267done:
2268 nullfree(path);
2269 nullfree(newpath);
2270 return stat;
2271}
2272
2273/*Provide an internal function for generating pseudo file descriptors
2274 for systems that are not file based (e.g. dap, memio).
2275*/
2276
2278static int pseudofd = 0;
2279
2287int
2288nc__pseudofd(void)
2289{
2290 if(pseudofd == 0) {
2291#ifdef HAVE_GETRLIMIT
2292 int maxfd = 32767; /* default */
2293 struct rlimit rl;
2294 if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
2295 if(rl.rlim_max != RLIM_INFINITY)
2296 maxfd = (int)rl.rlim_max;
2297 if(rl.rlim_cur != RLIM_INFINITY)
2298 maxfd = (int)rl.rlim_cur;
2299 }
2300 pseudofd = maxfd+1;
2301#endif
2302 }
2303 return pseudofd++;
2304}
int nc_inq_nvars(int ncid, int *nvarsp)
Learn the number of variables in a file or group.
Definition dfile.c:1684
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:216
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:500
int nc_close(int ncid)
Close an open netCDF dataset.
Definition dfile.c:1330
int nc_abort(int ncid)
No longer necessary for user to invoke manually.
Definition dfile.c:1277
int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
Definition dfile.c:428
int nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
Inquire about a file or group.
Definition dfile.c:1665
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:1612
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:1389
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:1148
int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
Definition dfile.c:1504
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:546
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:751
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:928
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:806
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:1758
int nc_enddef(int ncid)
Leave define mode.
Definition dfile.c:1057
int nc_redef(int ncid)
Put open netcdf dataset into define mode.
Definition dfile.c:993
int nc_open(const char *path, int omode, int *ncidp)
Open an existing netCDF file.
Definition dfile.c:694
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:871
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:1577
int nc_sync(int ncid)
Synchronize an open netcdf dataset to disk.
Definition dfile.c:1225
static int check_create_mode(int mode)
Check the create mode parameter for sanity.
Definition dfile.c:1805
#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
#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.