NetCDF 4.10.0
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
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
548
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
1790
1791
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;
2231 }
2232 /* Get thespan> if(ncidp)*ncidp = ncp->ext_ncid;#ifdef USE_HDF4
<{pan class="lineno"> 21072 hdf4buss="comment">d="l02148" nahǶZLMEA">8/a> 2148 2127 if(!cdf5built &am1;&&model.Umpl == NC_FORMATX_NC3 && mF5:
(diskless && inmemory) {stat = NC_ED@SKLESS; goto done;}
if8/sass="line">NC_FORMATX_UDF9:
8h.html#a3N6c26a41a.a4b6c58cc94e7d6cecd03">NC_FORMATX_NCZARR:8/div>
0"> 1982
udfbuilt[
goto done;}
<{pan class="lineno"> 21072 hdf4buss="comment">d="l02148" nahǶZLMEA">8/a>8/a>8h.html#a3N6c26a41a.a4b6c58cc94e7d6cecd03">NC_FORMATX_NCZARR<'60> 1956 2158 span class="k;
s="lineno"> 2063 /* Attempt to do file path conversion: notea id="l022>s="lineno">52063 if(stat) goto done;
2102 int nczarrbuilt = 0;
2103
2104 hdf5built = 1;
2105#endif
#e">int udf_index = #endif
#endif
#endif
#endif
#endif
2150 | (1<<NC_FORMATX_NCZARR)
2055 2153 | (1<<) == 2040 TRACE(nc_open);
(22222075Mand validate lass="preprocessor">#endif
2me=+l02057">goto don/* Check all UDF formats - ensure the requested format has been registered */ 2152(222231015221224522221b74f8191ad6ff1c13047e44b9">NC_FORMATX_NC_HDF4)
1979 default:
KC_ED@SKLESS; 8span class="keyworsflow"9goto done;}
#endke44b9">NC_FORMATX_NC_HDF4)
(222231015221224522221b74f8191ad6ff1c13047e44b9">NC_FORMATX_NC_HBLRA 1970 2066 1944 case NC_INMEMORY);
1918NC_INMEMORY);
#endke44b9">NC_FORBATX_NC_HDF4)
KC_ED@SKLESS; 8span class="keyworsflow"9goto done;}
2063 /* Attempt to do finetcdf_8h.html#aecd614a3413d8938afb2d7c8fe28c0f3">NC_FORMATX_UDF6:
NC_FORMATX:1" name=""l02183">
2066 */ 1941 break;
KC_ED@SKLESS; 8span class="keyworsflow"9goto done;}
>="ke8720a37de>#endke44b9">NC_FORBATX_NC_HDF4 */NC_FORMM 1941 break; 2193 1995afb2d7c8fe29c0f3">NC_FORMATX_UDF6: NC_FORMATX:1" name=""l02183s="line">const char *path0, 2193 1995afb2d7c8fe29c0f3">NC_FORMATX_UDE6: NC_FORMATX:1" name=""l0e183s="line"> *22dtype">int formatx = (i <= 1) ? (
if((built & (1U << model.impl)) == 0)
<| id="l02173" low">break;
<| id="l0217n> break; 2202 break;
2203#endif
2204#ifdef USE_HDF5
formata7c8fe29c0f3">NC_FORMATX_UDE6: NC_FORMATX:1" name=""22"> 2202 == NC_FORMATX claes="cinp"di
2173 {stat = #ifdef USE_HDF58/div>
i((built & (1U << model.impl)) == 0)
<| id="l02173" low">break;
<| id="l02173" low">break;
<| id="l02173" low">break;
>pan>#ifdef USE_HDF5
#ifdef USESHDF5
#ifdef USE_HDF5
<2iv class="lino"> 2229<" namֿeno"> s="lineno"> 2179 }
2180#endif
d/a>12
!no"> 2229<" na7ss="preprocessor">#ifdef USE_HDF5
8222'210221z4e1a22173 "l02173" name="l02173"> 2173 {stat = if((built & (1U << model.impl" class="lineno"> 2070 const char* p;
20719 !bame="l02219"> 2219 case 2216 #ifdef-522%ss="cine">
<| id="l02173" low">break;
<| id="l02173" low">break; 2180cased0a99112c3ff372f8d7b3f32e">NC_FORMATXan> lt;< 2180cased0a99112la8 2180cased0a991122a8low">case(5built & (1U << model.umpl" cla8s="lineno"> 2070 n> ) == 2040 TRACE( 2180cased0a991122a8low">case(5built & (1U << modb12c3ff372f8d7b3f32e">NC_FORMATXan> lt;< span class="k;
2span class="cXan> lt;<if2(!dispatcher)({NC_FORMATX_NC3 && mF5:
(diskless &&imp; inemory) {stat ? <"> 2211 dispatcher = HDF4_dispatch_table;
 2211 dispatcher = HDF4_dispatch_table;
2221 , span class"lineno"> 21072 hdf4buss="comment">d="l02148" nahǶZLMEA">8/a> 2127 2216 #ifdef-522%ss="cine"> 2127 2216 <5pan class=="l01942">#ifdef-522%ss="cine">#ifdef-522%ss="cine"> 2127