/src/netcdf-c/libdispatch/dfile.c
| Line | Count | Source | 
| 1 |  | /** | 
| 2 |  |  * @file | 
| 3 |  |  * | 
| 4 |  |  * File create and open functions | 
| 5 |  |  * | 
| 6 |  |  * These functions end up calling functions in one of the dispatch | 
| 7 |  |  * layers (netCDF-4, dap server, etc). | 
| 8 |  |  * | 
| 9 |  |  * Copyright 2018 University Corporation for Atmospheric | 
| 10 |  |  * Research/Unidata. See COPYRIGHT file for more info. | 
| 11 |  |  */ | 
| 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. */ | 
| 49 |  | NC_Dispatch *UDF0_dispatch_table = NULL; | 
| 50 |  | char UDF0_magic_number[NC_MAX_MAGIC_NUMBER_LEN + 1] = ""; | 
| 51 |  | NC_Dispatch *UDF1_dispatch_table = NULL; | 
| 52 |  | char UDF1_magic_number[NC_MAX_MAGIC_NUMBER_LEN + 1] = ""; | 
| 53 |  |  | 
| 54 |  | /**************************************************/ | 
| 55 |  |  | 
| 56 |  |  | 
| 57 |  | /** \defgroup datasets NetCDF File and Data I/O | 
| 58 |  |  | 
| 59 |  |     NetCDF opens datasets as files or remote access URLs. | 
| 60 |  |  | 
| 61 |  |     A netCDF dataset that has not yet been opened can only be referred to | 
| 62 |  |     by its dataset name. Once a netCDF dataset is opened, it is referred | 
| 63 |  |     to by a netCDF ID, which is a small non-negative integer returned when | 
| 64 |  |     you create or open the dataset. A netCDF ID is much like a file | 
| 65 |  |     descriptor in C or a logical unit number in FORTRAN. In any single | 
| 66 |  |     program, the netCDF IDs of distinct open netCDF datasets are | 
| 67 |  |     distinct. A single netCDF dataset may be opened multiple times and | 
| 68 |  |     will then have multiple distinct netCDF IDs; however at most one of | 
| 69 |  |     the open instances of a single netCDF dataset should permit | 
| 70 |  |     writing. When an open netCDF dataset is closed, the ID is no longer | 
| 71 |  |     associated with a netCDF dataset. | 
| 72 |  |  | 
| 73 |  |     Functions that deal with the netCDF library include: | 
| 74 |  |     - Get version of library. | 
| 75 |  |     - Get error message corresponding to a returned error code. | 
| 76 |  |  | 
| 77 |  |     The operations supported on a netCDF dataset as a single object are: | 
| 78 |  |     - Create, given dataset name and whether to overwrite or not. | 
| 79 |  |     - Open for access, given dataset name and read or write intent. | 
| 80 |  |     - Put into define mode, to add dimensions, variables, or attributes. | 
| 81 |  |     - Take out of define mode, checking consistency of additions. | 
| 82 |  |     - Close, writing to disk if required. | 
| 83 |  |     - Inquire about the number of dimensions, number of variables, | 
| 84 |  |     number of global attributes, and ID of the unlimited dimension, if | 
| 85 |  |     any. | 
| 86 |  |     - Synchronize to disk to make sure it is current. | 
| 87 |  |     - Set and unset nofill mode for optimized sequential writes. | 
| 88 |  |     - After a summary of conventions used in describing the netCDF | 
| 89 |  |     interfaces, the rest of this chapter presents a detailed description | 
| 90 |  |     of the interfaces for these operations. | 
| 91 |  | */ | 
| 92 |  |  | 
| 93 |  | /** | 
| 94 |  |  * Add handling of user-defined format. | 
| 95 |  |  * | 
| 96 |  |  * User-defined formats allow users to write a library which can read | 
| 97 |  |  * their own proprietary format as if it were netCDF. This allows | 
| 98 |  |  * existing netCDF codes to work on non-netCDF data formats. | 
| 99 |  |  * | 
| 100 |  |  * User-defined formats work by specifying a netCDF dispatch | 
| 101 |  |  * table. The dispatch table is a struct of (mostly) C function | 
| 102 |  |  * pointers. It contains pointers to the key functions of the netCDF | 
| 103 |  |  * API. Once these functions are provided, and the dispatch table is | 
| 104 |  |  * specified, the netcdf-c library can read any format. | 
| 105 |  |  * | 
| 106 |  |  * @note Unlike the public netCDF API, the dispatch table may not be | 
| 107 |  |  * backward compatible between netCDF releases. Instead, it contains a | 
| 108 |  |  * dispatch version number. If this number is not correct (i.e. does | 
| 109 |  |  * not match the current dispatch table version), then ::NC_EINVAL | 
| 110 |  |  * will be returned. | 
| 111 |  |  * | 
| 112 |  |  * @param mode_flag NC_UDF0 or NC_UDF1 | 
| 113 |  |  * @param dispatch_table Pointer to dispatch table to use for this user format. | 
| 114 |  |  * @param magic_number Magic number used to identify file. Ignored if | 
| 115 |  |  * NULL. | 
| 116 |  |  * | 
| 117 |  |  * @return ::NC_NOERR No error. | 
| 118 |  |  * @return ::NC_EINVAL Invalid input. | 
| 119 |  |  * @author Ed Hartnett | 
| 120 |  |  * @ingroup datasets | 
| 121 |  |  */ | 
| 122 |  | int | 
| 123 |  | nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number) | 
| 124 | 0 | { | 
| 125 |  |     /* Check inputs. */ | 
| 126 | 0 |     if (!dispatch_table) | 
| 127 | 0 |         return NC_EINVAL; | 
| 128 | 0 |     if (magic_number && strlen(magic_number) > NC_MAX_MAGIC_NUMBER_LEN) | 
| 129 | 0 |         return NC_EINVAL; | 
| 130 |  |  | 
| 131 |  |     /* Check the version of the dispatch table provided. */ | 
| 132 | 0 |     if (dispatch_table->dispatch_version != NC_DISPATCH_VERSION) | 
| 133 | 0 |         return NC_EINVAL; | 
| 134 |  |     /* user defined magic numbers not allowed with netcdf3 modes */  | 
| 135 | 0 |     if (magic_number && (fIsSet(mode_flag, NC_64BIT_OFFSET) || | 
| 136 | 0 |                          fIsSet(mode_flag, NC_64BIT_DATA) || | 
| 137 | 0 |                         (fIsSet(mode_flag, NC_CLASSIC_MODEL) && | 
| 138 | 0 |                         !fIsSet(mode_flag, NC_NETCDF4)))) | 
| 139 | 0 |         return NC_EINVAL; | 
| 140 |  |     /* Retain a pointer to the dispatch_table and a copy of the magic | 
| 141 |  |      * number, if one was provided. */ | 
| 142 | 0 |     if (fIsSet(mode_flag,NC_UDF0)) | 
| 143 | 0 |     { | 
| 144 | 0 |         UDF0_dispatch_table = dispatch_table; | 
| 145 | 0 |         if (magic_number) | 
| 146 | 0 |             strncpy(UDF0_magic_number, magic_number, NC_MAX_MAGIC_NUMBER_LEN); | 
| 147 | 0 |     } | 
| 148 | 0 |     else if(fIsSet(mode_flag, NC_UDF1)) | 
| 149 | 0 |     { | 
| 150 | 0 |         UDF1_dispatch_table = dispatch_table; | 
| 151 | 0 |         if (magic_number) | 
| 152 | 0 |             strncpy(UDF1_magic_number, magic_number, NC_MAX_MAGIC_NUMBER_LEN); | 
| 153 | 0 |     } | 
| 154 | 0 |     else | 
| 155 | 0 |     { | 
| 156 | 0 |         return NC_EINVAL; | 
| 157 | 0 |     } | 
| 158 |  |  | 
| 159 | 0 |     return NC_NOERR; | 
| 160 | 0 | } | 
| 161 |  |  | 
| 162 |  | /** | 
| 163 |  |  * Inquire about user-defined format. | 
| 164 |  |  * | 
| 165 |  |  * @param mode_flag NC_UDF0 or NC_UDF1 | 
| 166 |  |  * @param dispatch_table Pointer that gets pointer to dispatch table | 
| 167 |  |  * to use for this user format, or NULL if this user-defined format is | 
| 168 |  |  * not defined. Ignored if NULL. | 
| 169 |  |  * @param magic_number Pointer that gets magic number used to identify | 
| 170 |  |  * file, if one has been set. Magic number will be of max size | 
| 171 |  |  * NC_MAX_MAGIC_NUMBER_LEN. Ignored if NULL. | 
| 172 |  |  * | 
| 173 |  |  * @return ::NC_NOERR No error. | 
| 174 |  |  * @return ::NC_EINVAL Invalid input. | 
| 175 |  |  * @author Ed Hartnett | 
| 176 |  |  * @ingroup datasets | 
| 177 |  |  */ | 
| 178 |  | int | 
| 179 |  | nc_inq_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number) | 
| 180 | 0 | { | 
| 181 |  |     /* Check inputs. */ | 
| 182 | 0 |     if (fIsSet(mode_flag,NC_UDF0)) | 
| 183 | 0 |     { | 
| 184 | 0 |         if (dispatch_table) | 
| 185 | 0 |             *dispatch_table = UDF0_dispatch_table; | 
| 186 | 0 |         if (magic_number) | 
| 187 | 0 |             strncpy(magic_number, UDF0_magic_number, NC_MAX_MAGIC_NUMBER_LEN); | 
| 188 | 0 |     } | 
| 189 | 0 |     else if(fIsSet(mode_flag,NC_UDF1)) | 
| 190 | 0 |     { | 
| 191 | 0 |         if (dispatch_table) | 
| 192 | 0 |             *dispatch_table = UDF1_dispatch_table; | 
| 193 | 0 |         if (magic_number) | 
| 194 | 0 |             strncpy(magic_number, UDF1_magic_number, NC_MAX_MAGIC_NUMBER_LEN); | 
| 195 | 0 |     } | 
| 196 | 0 |     else | 
| 197 | 0 |     { | 
| 198 | 0 |         return NC_EINVAL; | 
| 199 | 0 |     } | 
| 200 |  |  | 
| 201 | 0 |     return NC_NOERR; | 
| 202 | 0 | } | 
| 203 |  |  | 
| 204 |  | /**  \ingroup datasets | 
| 205 |  |      Create a new netCDF file. | 
| 206 |  |  | 
| 207 |  |      This function creates a new netCDF dataset, returning a netCDF ID that | 
| 208 |  |      can subsequently be used to refer to the netCDF dataset in other | 
| 209 |  |      netCDF function calls. The new netCDF dataset opened for write access | 
| 210 |  |      and placed in define mode, ready for you to add dimensions, variables, | 
| 211 |  |      and attributes. | 
| 212 |  |  | 
| 213 |  |      \param path The file name of the new netCDF dataset. | 
| 214 |  |  | 
| 215 |  |      \param cmode The creation mode flag. The following flags are available: | 
| 216 |  |      NC_CLOBBER (overwrite existing file), | 
| 217 |  |      NC_NOCLOBBER (do not overwrite existing file), | 
| 218 |  |      NC_SHARE (limit write caching - netcdf classic files only), | 
| 219 |  |      NC_64BIT_OFFSET (create 64-bit offset file), | 
| 220 |  |      NC_64BIT_DATA (alias NC_CDF5) (create CDF-5 file), | 
| 221 |  |      NC_NETCDF4 (create netCDF-4/HDF5 file), | 
| 222 |  |      NC_CLASSIC_MODEL (enforce netCDF classic mode on netCDF-4/HDF5 files), | 
| 223 |  |      NC_DISKLESS (store data in memory), and | 
| 224 |  |      NC_PERSIST (force the NC_DISKLESS data from memory to a file), | 
| 225 |  |      NC_MMAP (use MMAP for NC_DISKLESS instead of NC_INMEMORY -- deprecated). | 
| 226 |  |      See discussion below. | 
| 227 |  |  | 
| 228 |  |      \param ncidp Pointer to location where returned netCDF ID is to be | 
| 229 |  |      stored. | 
| 230 |  |  | 
| 231 |  |      <h2>The cmode Flag</h2> | 
| 232 |  |  | 
| 233 |  |      The cmode flag is used to control the type of file created, and some | 
| 234 |  |      aspects of how it may be used. | 
| 235 |  |  | 
| 236 |  |      Setting NC_NOCLOBBER means you do not want to clobber (overwrite) an | 
| 237 |  |      existing dataset; an error (NC_EEXIST) is returned if the specified | 
| 238 |  |      dataset already exists. | 
| 239 |  |  | 
| 240 |  |      The NC_SHARE flag is appropriate when one process may be writing the | 
| 241 |  |      dataset and one or more other processes reading the dataset | 
| 242 |  |      concurrently; it means that dataset accesses are not buffered and | 
| 243 |  |      caching is limited. Since the buffering scheme is optimized for | 
| 244 |  |      sequential access, programs that do not access data sequentially may | 
| 245 |  |      see some performance improvement by setting the NC_SHARE flag. This | 
| 246 |  |      flag is ignored for netCDF-4 files. | 
| 247 |  |  | 
| 248 |  |      Setting NC_64BIT_OFFSET causes netCDF to create a 64-bit offset format | 
| 249 |  |      file, instead of a netCDF classic format file. The 64-bit offset | 
| 250 |  |      format imposes far fewer restrictions on very large (i.e. over 2 GB) | 
| 251 |  |      data files. See Large File Support. | 
| 252 |  |  | 
| 253 |  |      Setting NC_64BIT_DATA (alias NC_CDF5) causes netCDF to create a CDF-5 | 
| 254 |  |      file format that supports large files (i.e. over 2GB) and large | 
| 255 |  |      variables (over 2B array elements.). See Large File Support. | 
| 256 |  |  | 
| 257 |  |      A zero value (defined for convenience as NC_CLOBBER) specifies the | 
| 258 |  |      default behavior: overwrite any existing dataset with the same file | 
| 259 |  |      name and buffer and cache accesses for efficiency. The dataset will be | 
| 260 |  |      in netCDF classic format. See NetCDF Classic Format Limitations. | 
| 261 |  |  | 
| 262 |  |      Setting NC_NETCDF4 causes netCDF to create a HDF5/NetCDF-4 file. | 
| 263 |  |  | 
| 264 |  |      Setting NC_CLASSIC_MODEL causes netCDF to enforce the classic data | 
| 265 |  |      model in this file. (This only has effect for netCDF-4/HDF5 files, as | 
| 266 |  |      CDF-1, 2 and 5 files always use the classic model.) When | 
| 267 |  |      used with NC_NETCDF4, this flag ensures that the resulting | 
| 268 |  |      netCDF-4/HDF5 file may never contain any new constructs from the | 
| 269 |  |      enhanced data model. That is, it cannot contain groups, user defined | 
| 270 |  |      types, multiple unlimited dimensions, or new atomic types. The | 
| 271 |  |      advantage of this restriction is that such files are guaranteed to | 
| 272 |  |      work with existing netCDF software. | 
| 273 |  |  | 
| 274 |  |      Setting NC_DISKLESS causes netCDF to create the file only in | 
| 275 |  |      memory and to optionally write the final contents to the | 
| 276 |  |      correspondingly named disk file. This allows for the use of | 
| 277 |  |      files that have no long term purpose. Operating on an existing file | 
| 278 |  |      in memory may also be faster. The decision on whether | 
| 279 |  |      or not to "persist" the memory contents to a disk file is | 
| 280 |  |      described in detail in the file docs/inmemory.md, which is | 
| 281 |  |      definitive.  By default, closing a diskless fill will cause it's | 
| 282 |  |      contents to be lost. | 
| 283 |  |  | 
| 284 |  |      If NC_DISKLESS is going to be used for creating a large classic | 
| 285 |  |      file, it behooves one to use nc__create and specify an | 
| 286 |  |      appropriately large value of the initialsz parameter to avoid to | 
| 287 |  |      many extensions to the in-memory space for the file.  This flag | 
| 288 |  |      applies to files in classic format and to file in extended | 
| 289 |  |      format (netcdf-4). | 
| 290 |  |  | 
| 291 |  |      Note that nc_create(path,cmode,ncidp) is equivalent to the invocation of | 
| 292 |  |      nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp). | 
| 293 |  |  | 
| 294 |  |      \returns ::NC_NOERR No error. | 
| 295 |  |      \returns ::NC_EEXIST Specifying a file name of a file that exists and also specifying NC_NOCLOBBER. | 
| 296 |  |      \returns ::NC_EPERM Attempting to create a netCDF file in a directory where you do not have permission to create files. | 
| 297 |  |      \returns ::NC_ENOMEM System out of memory. | 
| 298 |  |      \returns ::NC_ENFILE Too many files open. | 
| 299 |  |      \returns ::NC_EHDFERR HDF5 error (netCDF-4 files only). | 
| 300 |  |      \returns ::NC_EFILEMETA Error writing netCDF-4 file-level metadata in | 
| 301 |  |      HDF5 file. (netCDF-4 files only). | 
| 302 |  |      \returns ::NC_EDISKLESS if there was an error in creating the | 
| 303 |  |      in-memory file. | 
| 304 |  |  | 
| 305 |  |      \note When creating a netCDF-4 file HDF5 error reporting is turned | 
| 306 |  |      off, if it is on. This doesn't stop the HDF5 error stack from | 
| 307 |  |      recording the errors, it simply stops their display to the user | 
| 308 |  |      through stderr. | 
| 309 |  |  | 
| 310 |  |      <h1>Examples</h1> | 
| 311 |  |  | 
| 312 |  |      In this example we create a netCDF dataset named foo.nc; we want the | 
| 313 |  |      dataset to be created in the current directory only if a dataset with | 
| 314 |  |      that name does not already exist: | 
| 315 |  |  | 
| 316 |  |      @code | 
| 317 |  |      #include <netcdf.h> | 
| 318 |  |      ... | 
| 319 |  |      int status = NC_NOERR; | 
| 320 |  |      int ncid; | 
| 321 |  |      ... | 
| 322 |  |      status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); | 
| 323 |  |      if (status != NC_NOERR) handle_error(status); | 
| 324 |  |      @endcode | 
| 325 |  |  | 
| 326 |  |      In this example we create a netCDF dataset named foo_large.nc. It will | 
| 327 |  |      be in the 64-bit offset format. | 
| 328 |  |  | 
| 329 |  |      @code | 
| 330 |  |      #include <netcdf.h> | 
| 331 |  |      ... | 
| 332 |  |      int status = NC_NOERR; | 
| 333 |  |      int ncid; | 
| 334 |  |      ... | 
| 335 |  |      status = nc_create("foo_large.nc", NC_NOCLOBBER|NC_64BIT_OFFSET, &ncid); | 
| 336 |  |      if (status != NC_NOERR) handle_error(status); | 
| 337 |  |      @endcode | 
| 338 |  |  | 
| 339 |  |      In this example we create a netCDF dataset named foo_HDF5.nc. It will | 
| 340 |  |      be in the HDF5 format. | 
| 341 |  |  | 
| 342 |  |      @code | 
| 343 |  |      #include <netcdf.h> | 
| 344 |  |      ... | 
| 345 |  |      int status = NC_NOERR; | 
| 346 |  |      int ncid; | 
| 347 |  |      ... | 
| 348 |  |      status = nc_create("foo_HDF5.nc", NC_NOCLOBBER|NC_NETCDF4, &ncid); | 
| 349 |  |      if (status != NC_NOERR) handle_error(status); | 
| 350 |  |      @endcode | 
| 351 |  |  | 
| 352 |  |      In this example we create a netCDF dataset named | 
| 353 |  |      foo_HDF5_classic.nc. It will be in the HDF5 format, but will not allow | 
| 354 |  |      the use of any netCDF-4 advanced features. That is, it will conform to | 
| 355 |  |      the classic netCDF-3 data model. | 
| 356 |  |  | 
| 357 |  |      @code | 
| 358 |  |      #include <netcdf.h> | 
| 359 |  |      ... | 
| 360 |  |      int status = NC_NOERR; | 
| 361 |  |      int ncid; | 
| 362 |  |      ... | 
| 363 |  |      status = nc_create("foo_HDF5_classic.nc", NC_NOCLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid); | 
| 364 |  |      if (status != NC_NOERR) handle_error(status); | 
| 365 |  |      @endcode | 
| 366 |  |  | 
| 367 |  |      In this example we create an in-memory netCDF classic dataset named | 
| 368 |  |      diskless.nc whose content will be lost when nc_close() is called. | 
| 369 |  |  | 
| 370 |  |      @code | 
| 371 |  |      #include <netcdf.h> | 
| 372 |  |      ... | 
| 373 |  |      int status = NC_NOERR; | 
| 374 |  |      int ncid; | 
| 375 |  |      ... | 
| 376 |  |      status = nc_create("diskless.nc", NC_DISKLESS, &ncid); | 
| 377 |  |      if (status != NC_NOERR) handle_error(status); | 
| 378 |  |      @endcode | 
| 379 |  |  | 
| 380 |  |      In this example we create a in-memory netCDF classic dataset named | 
| 381 |  |      diskless.nc and specify that it should be made persistent | 
| 382 |  |      in a file named diskless.nc when nc_close() is called. | 
| 383 |  |  | 
| 384 |  |      @code | 
| 385 |  |      #include <netcdf.h> | 
| 386 |  |      ... | 
| 387 |  |      int status = NC_NOERR; | 
| 388 |  |      int ncid; | 
| 389 |  |      ... | 
| 390 |  |      status = nc_create("diskless.nc", NC_DISKLESS|NC_PERSIST, &ncid); | 
| 391 |  |      if (status != NC_NOERR) handle_error(status); | 
| 392 |  |      @endcode | 
| 393 |  |  | 
| 394 |  |      A variant of nc_create(), nc__create() (note the double underscore) allows | 
| 395 |  |      users to specify two tuning parameters for the file that it is | 
| 396 |  |      creating.  */ | 
| 397 |  | int | 
| 398 |  | nc_create(const char *path, int cmode, int *ncidp) | 
| 399 | 0 | { | 
| 400 | 0 |     return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp); | 
| 401 | 0 | } | 
| 402 |  |  | 
| 403 |  | /** | 
| 404 |  |  * Create a netCDF file with some extra parameters controlling classic | 
| 405 |  |  * file caching. | 
| 406 |  |  * | 
| 407 |  |  * Like nc_create(), this function creates a netCDF file. | 
| 408 |  |  * | 
| 409 |  |  * @param path The file name of the new netCDF dataset. | 
| 410 |  |  * @param cmode The creation mode flag, the same as in nc_create(). | 
| 411 |  |  * @param initialsz On some systems, and with custom I/O layers, it | 
| 412 |  |  * may be advantageous to set the size of the output file at creation | 
| 413 |  |  * time. This parameter sets the initial size of the file at creation | 
| 414 |  |  * time. This only applies to classic CDF-1, 2, and 5 files.  The | 
| 415 |  |  * special value NC_SIZEHINT_DEFAULT (which is the value 0), lets the | 
| 416 |  |  * netcdf library choose a suitable initial size. | 
| 417 |  |  * @param chunksizehintp A pointer to the chunk size hint, which | 
| 418 |  |  * controls a space versus time tradeoff, memory allocated in the | 
| 419 |  |  * netcdf library versus number of system calls. Because of internal | 
| 420 |  |  * requirements, the value may not be set to exactly the value | 
| 421 |  |  * requested. The actual value chosen is returned by reference. Using | 
| 422 |  |  * a NULL pointer or having the pointer point to the value | 
| 423 |  |  * NC_SIZEHINT_DEFAULT causes the library to choose a default. How the | 
| 424 |  |  * system chooses the default depends on the system. On many systems, | 
| 425 |  |  * the "preferred I/O block size" is available from the stat() system | 
| 426 |  |  * call, struct stat member st_blksize. If this is available it is | 
| 427 |  |  * used. Lacking that, twice the system pagesize is used. Lacking a | 
| 428 |  |  * call to discover the system pagesize, we just set default bufrsize | 
| 429 |  |  * to 8192. The bufrsize is a property of a given open netcdf | 
| 430 |  |  * descriptor ncid, it is not a persistent property of the netcdf | 
| 431 |  |  * dataset. This only applies to classic files. | 
| 432 |  |  * @param ncidp Pointer to location where returned netCDF ID is to be | 
| 433 |  |  * stored. | 
| 434 |  |  * | 
| 435 |  |  * @note This function uses the same return codes as the nc_create() | 
| 436 |  |  * function. | 
| 437 |  |  * | 
| 438 |  |  * @returns ::NC_NOERR No error. | 
| 439 |  |  * @returns ::NC_ENOMEM System out of memory. | 
| 440 |  |  * @returns ::NC_EHDFERR HDF5 error (netCDF-4 files only). | 
| 441 |  |  * @returns ::NC_EFILEMETA Error writing netCDF-4 file-level metadata in | 
| 442 |  |  * HDF5 file. (netCDF-4 files only). | 
| 443 |  |  * @returns ::NC_EDISKLESS if there was an error in creating the | 
| 444 |  |  * in-memory file. | 
| 445 |  |  * | 
| 446 |  |  * <h1>Examples</h1> | 
| 447 |  |  * | 
| 448 |  |  * In this example we create a netCDF dataset named foo_large.nc; we | 
| 449 |  |  * want the dataset to be created in the current directory only if a | 
| 450 |  |  * dataset with that name does not already exist. We also specify that | 
| 451 |  |  * bufrsize and initial size for the file. | 
| 452 |  |  * | 
| 453 |  |  * @code | 
| 454 |  |  #include <netcdf.h> | 
| 455 |  |  ... | 
| 456 |  |  int status = NC_NOERR; | 
| 457 |  |  int ncid; | 
| 458 |  |  int intialsz = 2048; | 
| 459 |  |  int *bufrsize; | 
| 460 |  |  ... | 
| 461 |  |  *bufrsize = 1024; | 
| 462 |  |  status = nc__create("foo.nc", NC_NOCLOBBER, initialsz, bufrsize, &ncid); | 
| 463 |  |  if (status != NC_NOERR) handle_error(status); | 
| 464 |  |  @endcode | 
| 465 |  |  * | 
| 466 |  |  * @ingroup datasets | 
| 467 |  |  * @author Glenn Davis | 
| 468 |  |  */ | 
| 469 |  | int | 
| 470 |  | nc__create(const char *path, int cmode, size_t initialsz, | 
| 471 |  |            size_t *chunksizehintp, int *ncidp) | 
| 472 | 0 | { | 
| 473 | 0 |     return NC_create(path, cmode, initialsz, 0, | 
| 474 | 0 |                      chunksizehintp, 0, NULL, ncidp); | 
| 475 | 0 | } | 
| 476 |  |  | 
| 477 |  | /** \ingroup datasets | 
| 478 |  |     Create a netCDF file with the contents stored in memory. | 
| 479 |  |  | 
| 480 |  |     \param path Must be non-null, but otherwise only used to set the dataset name. | 
| 481 |  |  | 
| 482 |  |     \param mode the mode flags; Note that this procedure uses a limited set of flags because it forcibly sets NC_INMEMORY. | 
| 483 |  |  | 
| 484 |  |     \param initialsize (advisory) size to allocate for the created file | 
| 485 |  |  | 
| 486 |  |     \param ncidp Pointer to location where returned netCDF ID is to be | 
| 487 |  |     stored. | 
| 488 |  |  | 
| 489 |  |     \returns ::NC_NOERR No error. | 
| 490 |  |  | 
| 491 |  |     \returns ::NC_ENOMEM Out of memory. | 
| 492 |  |  | 
| 493 |  |     \returns ::NC_EDISKLESS diskless io is not enabled for fails. | 
| 494 |  |  | 
| 495 |  |     \returns ::NC_EINVAL, etc. other errors also returned by nc_open. | 
| 496 |  |  | 
| 497 |  |     <h1>Examples</h1> | 
| 498 |  |  | 
| 499 |  |     In this example we use nc_create_mem() to create a classic netCDF dataset | 
| 500 |  |     named foo.nc. The initial size is set to 4096. | 
| 501 |  |  | 
| 502 |  |     @code | 
| 503 |  |     #include <netcdf.h> | 
| 504 |  |     ... | 
| 505 |  |     int status = NC_NOERR; | 
| 506 |  |     int ncid; | 
| 507 |  |     int mode = 0; | 
| 508 |  |     size_t initialsize = 4096; | 
| 509 |  |     ... | 
| 510 |  |     status = nc_create_mem("foo.nc", mode, initialsize, &ncid); | 
| 511 |  |     if (status != NC_NOERR) handle_error(status); | 
| 512 |  |     @endcode | 
| 513 |  | */ | 
| 514 |  |  | 
| 515 |  | int | 
| 516 |  | nc_create_mem(const char* path, int mode, size_t initialsize, int* ncidp) | 
| 517 | 0 | { | 
| 518 | 0 |     if(mode & NC_MMAP) return NC_EINVAL; | 
| 519 | 0 |     mode |= NC_INMEMORY; /* Specifically, do not set NC_DISKLESS */ | 
| 520 | 0 |     return NC_create(path, mode, initialsize, 0, NULL, 0, NULL, ncidp); | 
| 521 | 0 | } | 
| 522 |  |  | 
| 523 |  | /** | 
| 524 |  |  * @internal Create a file with special (deprecated) Cray settings. | 
| 525 |  |  * | 
| 526 |  |  * @deprecated This function was used in the old days with the Cray at | 
| 527 |  |  * NCAR. The Cray is long gone, and this call is supported only for | 
| 528 |  |  * backward compatibility. Use nc_create() instead. | 
| 529 |  |  * | 
| 530 |  |  * @param path File name. | 
| 531 |  |  * @param cmode Create mode. | 
| 532 |  |  * @param initialsz Initial size of metadata region for classic files, | 
| 533 |  |  * ignored for other files. | 
| 534 |  |  * @param basepe Deprecated parameter from the Cray days. | 
| 535 |  |  * @param chunksizehintp A pointer to the chunk size hint. This only | 
| 536 |  |  * applies to classic files. | 
| 537 |  |  * @param ncidp Pointer that gets ncid. | 
| 538 |  |  * | 
| 539 |  |  * @return ::NC_NOERR No error. | 
| 540 |  |  * @author Glenn Davis | 
| 541 |  |  */ | 
| 542 |  | int | 
| 543 |  | nc__create_mp(const char *path, int cmode, size_t initialsz, | 
| 544 |  |               int basepe, size_t *chunksizehintp, int *ncidp) | 
| 545 | 0 | { | 
| 546 | 0 |     return NC_create(path, cmode, initialsz, basepe, | 
| 547 | 0 |                      chunksizehintp, 0, NULL, ncidp); | 
| 548 | 0 | } | 
| 549 |  |  | 
| 550 |  | /** | 
| 551 |  |  * Open an existing netCDF file. | 
| 552 |  |  * | 
| 553 |  |  * This function opens an existing netCDF dataset for access. It | 
| 554 |  |  * determines the underlying file format automatically. Use the same | 
| 555 |  |  * call to open a netCDF classic or netCDF-4 file. | 
| 556 |  |  * | 
| 557 |  |  * @param path File name for netCDF dataset to be opened. When the dataset | 
| 558 |  |  * is located on some remote server, then the path may be an OPeNDAP URL | 
| 559 |  |  * rather than a file path. | 
| 560 |  |  * @param omode The open mode flag may include NC_WRITE (for read/write | 
| 561 |  |  * access) and NC_SHARE (see below) and NC_DISKLESS (see below). | 
| 562 |  |  * @param ncidp Pointer to location where returned netCDF ID is to be | 
| 563 |  |  * stored. | 
| 564 |  |  * | 
| 565 |  |  * <h2>Open Mode</h2> | 
| 566 |  |  * | 
| 567 |  |  * A zero value (or ::NC_NOWRITE) specifies the default behavior: open | 
| 568 |  |  * the dataset with read-only access, buffering and caching accesses | 
| 569 |  |  * for efficiency. | 
| 570 |  |  * | 
| 571 |  |  * Otherwise, the open mode is ::NC_WRITE, ::NC_SHARE, or | 
| 572 |  |  * ::NC_WRITE|::NC_SHARE. Setting the ::NC_WRITE flag opens the | 
| 573 |  |  * dataset with read-write access. ("Writing" means any kind of change | 
| 574 |  |  * to the dataset, including appending or changing data, adding or | 
| 575 |  |  * renaming dimensions, variables, and attributes, or deleting | 
| 576 |  |  * attributes.) | 
| 577 |  |  * | 
| 578 |  |  * The NC_SHARE flag is only used for netCDF classic | 
| 579 |  |  * files. It is appropriate when one process may be writing the | 
| 580 |  |  * dataset and one or more other processes reading the dataset | 
| 581 |  |  * concurrently; it means that dataset accesses are not buffered and | 
| 582 |  |  * caching is limited. Since the buffering scheme is optimized for | 
| 583 |  |  * sequential access, programs that do not access data sequentially | 
| 584 |  |  * may see some performance improvement by setting the NC_SHARE flag. | 
| 585 |  |  * | 
| 586 |  |  * This procedure may also be invoked with the NC_DISKLESS flag set in | 
| 587 |  |  * the omode argument if the file to be opened is a classic format | 
| 588 |  |  * file.  For nc_open(), this flag applies only to files in classic | 
| 589 |  |  * format.  If the file is of type NC_NETCDF4, then the NC_DISKLESS | 
| 590 |  |  * flag will be ignored. | 
| 591 |  |  * | 
| 592 |  |  * If NC_DISKLESS is specified, then the whole file is read completely | 
| 593 |  |  * into memory. In effect this creates an in-memory cache of the file. | 
| 594 |  |  * If the omode flag also specifies NC_PERSIST, then the in-memory cache | 
| 595 |  |  * will be re-written to the disk file when nc_close() is called.  For | 
| 596 |  |  * some kinds of manipulations, having the in-memory cache can speed | 
| 597 |  |  * up file processing. But in simple cases, non-cached processing may | 
| 598 |  |  * actually be faster than using cached processing.  You will need to | 
| 599 |  |  * experiment to determine if the in-memory caching is worthwhile for | 
| 600 |  |  * your application. | 
| 601 |  |  * | 
| 602 |  |  * Normally, NC_DISKLESS allocates space in the heap for storing the | 
| 603 |  |  * in-memory file. If, however, the ./configure flags --enable-mmap is | 
| 604 |  |  * used, and the additional omode flag NC_MMAP is specified, then the | 
| 605 |  |  * file will be opened using the operating system MMAP facility.  This | 
| 606 |  |  * flag only applies to files in classic format. Extended format | 
| 607 |  |  * (netcdf-4) files will ignore the NC_MMAP flag. | 
| 608 |  |  * | 
| 609 |  |  * In most cases, using MMAP provides no advantage for just | 
| 610 |  |  * NC_DISKLESS. The one case where using MMAP is an advantage is when | 
| 611 |  |  * a file is to be opened and only a small portion of its data is to | 
| 612 |  |  * be read and/or written.  In this scenario, MMAP will cause only the | 
| 613 |  |  * accessed data to be retrieved from disk. Without MMAP, NC_DISKLESS | 
| 614 |  |  * will read the whole file into memory on nc_open. Thus, MMAP will | 
| 615 |  |  * provide some performance improvement in this case. | 
| 616 |  |  * | 
| 617 |  |  * It is not necessary to pass any information about the format of the | 
| 618 |  |  * file being opened. The file type will be detected automatically by | 
| 619 |  |  * the netCDF library. | 
| 620 |  |  * | 
| 621 |  |  * If a the path is a DAP URL, then the open mode is read-only. | 
| 622 |  |  * Setting NC_WRITE will be ignored. | 
| 623 |  |  * | 
| 624 |  |  * As of version 4.3.1.2, multiple calls to nc_open with the same | 
| 625 |  |  * path will return the same ncid value. | 
| 626 |  |  * | 
| 627 |  |  * @note When opening a netCDF-4 file HDF5 error reporting is turned | 
| 628 |  |  * off, if it is on. This doesn't stop the HDF5 error stack from | 
| 629 |  |  * recording the errors, it simply stops their display to the user | 
| 630 |  |  * through stderr. | 
| 631 |  |  * | 
| 632 |  |  * nc_open()returns the value NC_NOERR if no errors | 
| 633 |  |  * occurred. Otherwise, the returned status indicates an | 
| 634 |  |  * error. Possible causes of errors include: | 
| 635 |  |  * | 
| 636 |  |  * Note that nc_open(path,omode,ncidp) is equivalent to the invocation | 
| 637 |  |  * of nc__open(path,omode,NC_SIZEHINT_DEFAULT,NULL,ncidp). | 
| 638 |  |  * | 
| 639 |  |  * @returns ::NC_NOERR No error. | 
| 640 |  |  * @returns ::NC_EPERM Attempting to create a netCDF file in a directory where you do not have permission to open files. | 
| 641 |  |  * @returns ::NC_ENFILE Too many files open | 
| 642 |  |  * @returns ::NC_ENOMEM Out of memory. | 
| 643 |  |  * @returns ::NC_EHDFERR HDF5 error. (NetCDF-4 files only.) | 
| 644 |  |  * @returns ::NC_EDIMMETA Error in netCDF-4 dimension metadata. (NetCDF-4 files only.) | 
| 645 |  |  * | 
| 646 |  |  * <h1>Examples</h1> | 
| 647 |  |  * | 
| 648 |  |  * Here is an example using nc_open()to open an existing netCDF dataset | 
| 649 |  |  * named foo.nc for read-only, non-shared access: | 
| 650 |  |  * | 
| 651 |  |  * @code | 
| 652 |  |  * #include <netcdf.h> | 
| 653 |  |  *   ... | 
| 654 |  |  * int status = NC_NOERR; | 
| 655 |  |  * int ncid; | 
| 656 |  |  *   ... | 
| 657 |  |  * status = nc_open("foo.nc", 0, &ncid); | 
| 658 |  |  * if (status != NC_NOERR) handle_error(status); | 
| 659 |  |  * @endcode | 
| 660 |  |  * @ingroup datasets | 
| 661 |  |  * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner | 
| 662 |  |  */ | 
| 663 |  | int | 
| 664 |  | nc_open(const char *path, int omode, int *ncidp) | 
| 665 | 0 | { | 
| 666 | 0 |     return NC_open(path, omode, 0, NULL, 0, NULL, ncidp); | 
| 667 | 0 | } | 
| 668 |  |  | 
| 669 |  | /** \ingroup datasets | 
| 670 |  |     Open a netCDF file with extra performance parameters for the classic | 
| 671 |  |     library. | 
| 672 |  |  | 
| 673 |  |     \param path File name for netCDF dataset to be opened. When DAP | 
| 674 |  |     support is enabled, then the path may be an OPeNDAP URL rather than a | 
| 675 |  |     file path. | 
| 676 |  |  | 
| 677 |  |     \param omode The open mode flag may include NC_WRITE (for read/write | 
| 678 |  |     access) and NC_SHARE as in nc_open(). | 
| 679 |  |  | 
| 680 |  |     \param chunksizehintp A size hint for the classic library. Only | 
| 681 |  |     applies to classic files. See below for more | 
| 682 |  |     information. | 
| 683 |  |  | 
| 684 |  |     \param ncidp Pointer to location where returned netCDF ID is to be | 
| 685 |  |     stored. | 
| 686 |  |  | 
| 687 |  |     <h1>The chunksizehintp Parameter</h1> | 
| 688 |  |  | 
| 689 |  |     The argument referenced by bufrsizehintp controls a space versus time | 
| 690 |  |     tradeoff, memory allocated in the netcdf library versus number of | 
| 691 |  |     system calls. | 
| 692 |  |  | 
| 693 |  |     Because of internal requirements, the value may not be set to exactly | 
| 694 |  |     the value requested. The actual value chosen is returned by reference. | 
| 695 |  |  | 
| 696 |  |     Using a NULL pointer or having the pointer point to the value | 
| 697 |  |     NC_SIZEHINT_DEFAULT causes the library to choose a default. | 
| 698 |  |     How the system chooses the default depends on the system. On | 
| 699 |  |     many systems, the "preferred I/O block size" is available from the | 
| 700 |  |     stat() system call, struct stat member st_blksize. If this is | 
| 701 |  |     available it is used. Lacking that, twice the system pagesize is used. | 
| 702 |  |  | 
| 703 |  |     Lacking a call to discover the system pagesize, we just set default | 
| 704 |  |     bufrsize to 8192. | 
| 705 |  |  | 
| 706 |  |     The bufrsize is a property of a given open netcdf descriptor ncid, it | 
| 707 |  |     is not a persistent property of the netcdf dataset. | 
| 708 |  |  | 
| 709 |  |  | 
| 710 |  |     \returns ::NC_NOERR No error. | 
| 711 |  |  | 
| 712 |  |     \returns ::NC_ENOMEM Out of memory. | 
| 713 |  |  | 
| 714 |  |     \returns ::NC_EHDFERR HDF5 error. (NetCDF-4 files only.) | 
| 715 |  |  | 
| 716 |  |     \returns ::NC_EDIMMETA Error in netCDF-4 dimension metadata. (NetCDF-4 | 
| 717 |  |     files only.) | 
| 718 |  |  | 
| 719 |  | */ | 
| 720 |  | int | 
| 721 |  | nc__open(const char *path, int omode, | 
| 722 |  |          size_t *chunksizehintp, int *ncidp) | 
| 723 | 0 | { | 
| 724 |  |     /* this API is for non-parallel access. | 
| 725 |  |      * Note nc_open_par() also calls NC_open(). | 
| 726 |  |      */ | 
| 727 | 0 |     return NC_open(path, omode, 0, chunksizehintp, 0, NULL, ncidp); | 
| 728 | 0 | } | 
| 729 |  |  | 
| 730 |  | /** \ingroup datasets | 
| 731 |  |     Open a netCDF file with the contents taken from a block of memory. | 
| 732 |  |  | 
| 733 |  |     \param path Must be non-null, but otherwise only used to set the dataset name. | 
| 734 |  |  | 
| 735 |  |     \param omode the open mode flags; Note that this procedure uses a limited set of flags because it forcibly sets NC_INMEMORY. | 
| 736 |  |  | 
| 737 |  |     \param size The length of the block of memory being passed. | 
| 738 |  |  | 
| 739 |  |     \param memory Pointer to the block of memory containing the contents | 
| 740 |  |     of a netcdf file. | 
| 741 |  |  | 
| 742 |  |     \param ncidp Pointer to location where returned netCDF ID is to be | 
| 743 |  |     stored. | 
| 744 |  |  | 
| 745 |  |     \returns ::NC_NOERR No error. | 
| 746 |  |  | 
| 747 |  |     \returns ::NC_ENOMEM Out of memory. | 
| 748 |  |  | 
| 749 |  |     \returns ::NC_EDISKLESS diskless io is not enabled for fails. | 
| 750 |  |  | 
| 751 |  |     \returns ::NC_EINVAL, etc. other errors also returned by nc_open. | 
| 752 |  |  | 
| 753 |  |     <h1>Examples</h1> | 
| 754 |  |  | 
| 755 |  |     Here is an example using nc_open_mem() to open an existing netCDF dataset | 
| 756 |  |     named foo.nc for read-only, non-shared access. It differs from the nc_open() | 
| 757 |  |     example in that it assumes the contents of foo.nc have been read into memory. | 
| 758 |  |  | 
| 759 |  |     @code | 
| 760 |  |     #include <netcdf.h> | 
| 761 |  |     #include <netcdf_mem.h> | 
| 762 |  |     ... | 
| 763 |  |     int status = NC_NOERR; | 
| 764 |  |     int ncid; | 
| 765 |  |     size_t size; | 
| 766 |  |     void* memory; | 
| 767 |  |     ... | 
| 768 |  |     size = <compute file size of foo.nc in bytes>; | 
| 769 |  |     memory = malloc(size); | 
| 770 |  |     ... | 
| 771 |  |     status = nc_open_mem("foo.nc", 0, size, memory, &ncid); | 
| 772 |  |     if (status != NC_NOERR) handle_error(status); | 
| 773 |  |     @endcode | 
| 774 |  | */ | 
| 775 |  | int | 
| 776 |  | nc_open_mem(const char* path, int omode, size_t size, void* memory, int* ncidp) | 
| 777 | 339 | { | 
| 778 | 339 |     NC_memio meminfo; | 
| 779 |  |  | 
| 780 |  |     /* Sanity checks */ | 
| 781 | 339 |     if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL) | 
| 782 | 0 |         return NC_EINVAL; | 
| 783 | 339 |     if(omode & (NC_WRITE|NC_MMAP)) | 
| 784 | 0 |         return NC_EINVAL; | 
| 785 | 339 |     omode |= (NC_INMEMORY); /* Note: NC_INMEMORY and NC_DISKLESS are mutually exclusive*/ | 
| 786 | 339 |     meminfo.size = size; | 
| 787 | 339 |     meminfo.memory = memory; | 
| 788 | 339 |     meminfo.flags = NC_MEMIO_LOCKED; | 
| 789 | 339 |     return NC_open(path, omode, 0, NULL, 0, &meminfo, ncidp); | 
| 790 | 339 | } | 
| 791 |  |  | 
| 792 |  | /** \ingroup datasets | 
| 793 |  |     Open a netCDF file with the contents taken from a block of memory. | 
| 794 |  |     Similar to nc_open_mem, but with parameters. Warning: if you do | 
| 795 |  |     specify that the provided memory is locked, then <b>never</b> | 
| 796 |  |     pass in non-heap allocated memory. Additionally, if not locked, | 
| 797 |  |     then do not assume that the memory returned by nc_close_mem | 
| 798 |  |     is the same as passed to nc_open_memio. You <b>must</b> check | 
| 799 |  |     before attempting to free the original memory. | 
| 800 |  |  | 
| 801 |  |     \param path Must be non-null, but otherwise only used to set the dataset name. | 
| 802 |  |  | 
| 803 |  |     \param omode the open mode flags; Note that this procedure uses a limited set of flags because it forcibly sets NC_INMEMORY. | 
| 804 |  |  | 
| 805 |  |     \param params controlling parameters | 
| 806 |  |  | 
| 807 |  |     \param ncidp Pointer to location where returned netCDF ID is to be | 
| 808 |  |     stored. | 
| 809 |  |  | 
| 810 |  |     \returns ::NC_NOERR No error. | 
| 811 |  |  | 
| 812 |  |     \returns ::NC_ENOMEM Out of memory. | 
| 813 |  |  | 
| 814 |  |     \returns ::NC_EDISKLESS diskless io is not enabled for fails. | 
| 815 |  |  | 
| 816 |  |     \returns ::NC_EINVAL, etc. other errors also returned by nc_open. | 
| 817 |  |  | 
| 818 |  |     <h1>Examples</h1> | 
| 819 |  |  | 
| 820 |  |     Here is an example using nc_open_memio() to open an existing netCDF dataset | 
| 821 |  |     named foo.nc for read-only, non-shared access. It differs from the nc_open_mem() | 
| 822 |  |     example in that it uses a parameter block. | 
| 823 |  |  | 
| 824 |  |     @code | 
| 825 |  |     #include <netcdf.h> | 
| 826 |  |     #include <netcdf_mem.h> | 
| 827 |  |     ... | 
| 828 |  |     int status = NC_NOERR; | 
| 829 |  |     int ncid; | 
| 830 |  |     NC_memio params; | 
| 831 |  |     ... | 
| 832 |  |     params.size = <compute file size of foo.nc in bytes>; | 
| 833 |  |     params.memory = malloc(size); | 
| 834 |  |     params.flags = <see netcdf_mem.h> | 
| 835 |  |     ... | 
| 836 |  |     status = nc_open_memio("foo.nc", 0, ¶ms, &ncid); | 
| 837 |  |     if (status != NC_NOERR) handle_error(status); | 
| 838 |  |     @endcode | 
| 839 |  | */ | 
| 840 |  | int | 
| 841 |  | nc_open_memio(const char* path, int omode, NC_memio* params, int* ncidp) | 
| 842 | 0 | { | 
| 843 |  |     /* Sanity checks */ | 
| 844 | 0 |     if(path == NULL || params == NULL) | 
| 845 | 0 |         return NC_EINVAL; | 
| 846 | 0 |     if(params->memory == NULL || params->size < MAGIC_NUMBER_LEN) | 
| 847 | 0 |         return NC_EINVAL; | 
| 848 |  |  | 
| 849 | 0 |     if(omode & NC_MMAP) | 
| 850 | 0 |         return NC_EINVAL; | 
| 851 | 0 |     omode |= (NC_INMEMORY); | 
| 852 | 0 |     return NC_open(path, omode, 0, NULL, 0, params, ncidp); | 
| 853 | 0 | } | 
| 854 |  |  | 
| 855 |  | /** | 
| 856 |  |  * @internal Open a netCDF file with extra parameters for Cray. | 
| 857 |  |  * | 
| 858 |  |  * @deprecated This function was used in the old days with the Cray at | 
| 859 |  |  * NCAR. The Cray is long gone, and this call is supported only for | 
| 860 |  |  * backward compatibility. Use nc_open() instead. | 
| 861 |  |  * | 
| 862 |  |  * @param path The file name of the new netCDF dataset. | 
| 863 |  |  * @param omode Open mode. | 
| 864 |  |  * @param basepe Deprecated parameter from the Cray days. | 
| 865 |  |  * @param chunksizehintp A pointer to the chunk size hint. This only | 
| 866 |  |  * applies to classic files. | 
| 867 |  |  * @param ncidp Pointer to location where returned netCDF ID is to be | 
| 868 |  |  * stored. | 
| 869 |  |  * | 
| 870 |  |  * @return ::NC_NOERR | 
| 871 |  |  * @author Glenn Davis | 
| 872 |  |  */ | 
| 873 |  | int | 
| 874 |  | nc__open_mp(const char *path, int omode, int basepe, | 
| 875 |  |             size_t *chunksizehintp, int *ncidp) | 
| 876 | 0 | { | 
| 877 | 0 |     return NC_open(path, omode, basepe, chunksizehintp, 0, NULL, ncidp); | 
| 878 | 0 | } | 
| 879 |  |  | 
| 880 |  | /** \ingroup datasets | 
| 881 |  |     Get the file pathname (or the opendap URL) which was used to | 
| 882 |  |     open/create the ncid's file. | 
| 883 |  |  | 
| 884 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 885 |  |     nc_create(). | 
| 886 |  |  | 
| 887 |  |     \param pathlen Pointer where length of path will be returned. Ignored | 
| 888 |  |     if NULL. | 
| 889 |  |  | 
| 890 |  |     \param path Pointer where path name will be copied. Space must already | 
| 891 |  |     be allocated. Ignored if NULL. | 
| 892 |  |  | 
| 893 |  |     \returns ::NC_NOERR No error. | 
| 894 |  |  | 
| 895 |  |     \returns ::NC_EBADID Invalid ncid passed. | 
| 896 |  | */ | 
| 897 |  | int | 
| 898 |  | nc_inq_path(int ncid, size_t *pathlen, char *path) | 
| 899 | 0 | { | 
| 900 | 0 |     NC* ncp; | 
| 901 | 0 |     int stat = NC_NOERR; | 
| 902 | 0 |     if ((stat = NC_check_id(ncid, &ncp))) | 
| 903 | 0 |         return stat; | 
| 904 | 0 |     if(ncp->path == NULL) { | 
| 905 | 0 |         if(pathlen) *pathlen = 0; | 
| 906 | 0 |         if(path) path[0] = '\0'; | 
| 907 | 0 |     } else { | 
| 908 | 0 |         if (pathlen) *pathlen = strlen(ncp->path); | 
| 909 | 0 |         if (path) strcpy(path, ncp->path); | 
| 910 | 0 |     } | 
| 911 | 0 |     return stat; | 
| 912 | 0 | } | 
| 913 |  |  | 
| 914 |  | /** \ingroup datasets | 
| 915 |  |     Put open netcdf dataset into define mode | 
| 916 |  |  | 
| 917 |  |     The function nc_redef puts an open netCDF dataset into define mode, so | 
| 918 |  |     dimensions, variables, and attributes can be added or renamed and | 
| 919 |  |     attributes can be deleted. | 
| 920 |  |  | 
| 921 |  |     For netCDF-4 files (i.e. files created with NC_NETCDF4 in the cmode in | 
| 922 |  |     their call to nc_create()), it is not necessary to call nc_redef() | 
| 923 |  |     unless the file was also created with NC_STRICT_NC3. For straight-up | 
| 924 |  |     netCDF-4 files, nc_redef() is called automatically, as needed. | 
| 925 |  |  | 
| 926 |  |     For all netCDF-4 files, the root ncid must be used. This is the ncid | 
| 927 |  |     returned by nc_open() and nc_create(), and points to the root of the | 
| 928 |  |     hierarchy tree for netCDF-4 files. | 
| 929 |  |  | 
| 930 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 931 |  |     nc_create(). | 
| 932 |  |  | 
| 933 |  |     \returns ::NC_NOERR No error. | 
| 934 |  |  | 
| 935 |  |     \returns ::NC_EBADID Bad ncid. | 
| 936 |  |  | 
| 937 |  |     \returns ::NC_EBADGRPID The ncid must refer to the root group of the | 
| 938 |  |     file, that is, the group returned by nc_open() or nc_create(). | 
| 939 |  |  | 
| 940 |  |     \returns ::NC_EINDEFINE Already in define mode. | 
| 941 |  |  | 
| 942 |  |     \returns ::NC_EPERM File is read-only. | 
| 943 |  |  | 
| 944 |  |     <h1>Example</h1> | 
| 945 |  |  | 
| 946 |  |     Here is an example using nc_redef to open an existing netCDF dataset | 
| 947 |  |     named foo.nc and put it into define mode: | 
| 948 |  |  | 
| 949 |  |     \code | 
| 950 |  |     #include <netcdf.h> | 
| 951 |  |     ... | 
| 952 |  |     int status = NC_NOERR; | 
| 953 |  |     int ncid; | 
| 954 |  |     ... | 
| 955 |  |     status = nc_open("foo.nc", NC_WRITE, &ncid); | 
| 956 |  |     if (status != NC_NOERR) handle_error(status); | 
| 957 |  |     ... | 
| 958 |  |     status = nc_redef(ncid); | 
| 959 |  |     if (status != NC_NOERR) handle_error(status); | 
| 960 |  |     \endcode | 
| 961 |  | */ | 
| 962 |  | int | 
| 963 |  | nc_redef(int ncid) | 
| 964 | 0 | { | 
| 965 | 0 |     NC* ncp; | 
| 966 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 967 | 0 |     if(stat != NC_NOERR) return stat; | 
| 968 | 0 |     return ncp->dispatch->redef(ncid); | 
| 969 | 0 | } | 
| 970 |  |  | 
| 971 |  | /** \ingroup datasets | 
| 972 |  |     Leave define mode | 
| 973 |  |  | 
| 974 |  |     The function nc_enddef() takes an open netCDF dataset out of define | 
| 975 |  |     mode. The changes made to the netCDF dataset while it was in define | 
| 976 |  |     mode are checked and committed to disk if no problems | 
| 977 |  |     occurred. Non-record variables may be initialized to a "fill value" as | 
| 978 |  |     well with nc_set_fill(). The netCDF dataset is then placed in data | 
| 979 |  |     mode, so variable data can be read or written. | 
| 980 |  |  | 
| 981 |  |     It's not necessary to call nc_enddef() for netCDF-4 files. With netCDF-4 | 
| 982 |  |     files, nc_enddef() is called when needed by the netcdf-4 library. User | 
| 983 |  |     calls to nc_enddef() for netCDF-4 files still flush the metadata to | 
| 984 |  |     disk. | 
| 985 |  |  | 
| 986 |  |     This call may involve copying data under some circumstances. For a | 
| 987 |  |     more extensive discussion see File Structure and Performance. | 
| 988 |  |  | 
| 989 |  |     For netCDF-4/HDF5 format files there are some variable settings (the | 
| 990 |  |     compression, endianness, fletcher32 error correction, and fill value) | 
| 991 |  |     which must be set (if they are going to be set at all) between the | 
| 992 |  |     nc_def_var() and the next nc_enddef(). Once the nc_enddef() is called, | 
| 993 |  |     these settings can no longer be changed for a variable. | 
| 994 |  |  | 
| 995 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 996 |  |     nc_create(). | 
| 997 |  |  | 
| 998 |  |     If you use a group id (in a netCDF-4/HDF5 file), the enddef | 
| 999 |  |     will apply to the entire file. That means the enddef will not just end | 
| 1000 |  |     define mode in one group, but in the entire file. | 
| 1001 |  |  | 
| 1002 |  |     \returns ::NC_NOERR no error | 
| 1003 |  |  | 
| 1004 |  |     \returns ::NC_EBADID Invalid ncid passed. | 
| 1005 |  |  | 
| 1006 |  |     <h1>Example</h1> | 
| 1007 |  |  | 
| 1008 |  |     Here is an example using nc_enddef() to finish the definitions of a new | 
| 1009 |  |     netCDF dataset named foo.nc and put it into data mode: | 
| 1010 |  |  | 
| 1011 |  |     \code | 
| 1012 |  |     #include <netcdf.h> | 
| 1013 |  |     ... | 
| 1014 |  |     int status = NC_NOERR; | 
| 1015 |  |     int ncid; | 
| 1016 |  |     ... | 
| 1017 |  |     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); | 
| 1018 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1019 |  |  | 
| 1020 |  |     ...  create dimensions, variables, attributes | 
| 1021 |  |  | 
| 1022 |  |     status = nc_enddef(ncid); | 
| 1023 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1024 |  |     \endcode | 
| 1025 |  | */ | 
| 1026 |  | int | 
| 1027 |  | nc_enddef(int ncid) | 
| 1028 | 0 | { | 
| 1029 | 0 |     int status = NC_NOERR; | 
| 1030 | 0 |     NC *ncp; | 
| 1031 | 0 |     status = NC_check_id(ncid, &ncp); | 
| 1032 | 0 |     if(status != NC_NOERR) return status; | 
| 1033 | 0 |     return ncp->dispatch->_enddef(ncid,0,1,0,1); | 
| 1034 | 0 | } | 
| 1035 |  |  | 
| 1036 |  | /** \ingroup datasets | 
| 1037 |  |     Leave define mode with performance tuning | 
| 1038 |  |  | 
| 1039 |  |     The function nc__enddef takes an open netCDF dataset out of define | 
| 1040 |  |     mode. The changes made to the netCDF dataset while it was in define | 
| 1041 |  |     mode are checked and committed to disk if no problems | 
| 1042 |  |     occurred. Non-record variables may be initialized to a "fill value" as | 
| 1043 |  |     well with nc_set_fill(). The netCDF dataset is then placed in data mode, | 
| 1044 |  |     so variable data can be read or written. | 
| 1045 |  |  | 
| 1046 |  |     This call may involve copying data under some circumstances. For a | 
| 1047 |  |     more extensive discussion see File Structure and Performance. | 
| 1048 |  |  | 
| 1049 |  |     \warning This function exposes internals of the netcdf version 1 file | 
| 1050 |  |     format. Users should use nc_enddef() in most circumstances. This | 
| 1051 |  |     function may not be available on future netcdf implementations. | 
| 1052 |  |  | 
| 1053 |  |     The classic netcdf file format has three sections, the "header" | 
| 1054 |  |     section, the data section for fixed size variables, and the data | 
| 1055 |  |     section for variables which have an unlimited dimension (record | 
| 1056 |  |     variables). | 
| 1057 |  |  | 
| 1058 |  |     The header begins at the beginning of the file. The index (offset) of | 
| 1059 |  |     the beginning of the other two sections is contained in the | 
| 1060 |  |     header. Typically, there is no space between the sections. This causes | 
| 1061 |  |     copying overhead to accrue if one wishes to change the size of the | 
| 1062 |  |     sections, as may happen when changing names of things, text attribute | 
| 1063 |  |     values, adding attributes or adding variables. Also, for buffered i/o, | 
| 1064 |  |     there may be advantages to aligning sections in certain ways. | 
| 1065 |  |  | 
| 1066 |  |     The minfree parameters allow one to control costs of future calls to | 
| 1067 |  |     nc_redef, nc_enddef() by requesting that minfree bytes be available at | 
| 1068 |  |     the end of the section. | 
| 1069 |  |  | 
| 1070 |  |     The align parameters allow one to set the alignment of the beginning | 
| 1071 |  |     of the corresponding sections. The beginning of the section is rounded | 
| 1072 |  |     up to an index which is a multiple of the align parameter. The flag | 
| 1073 |  |     value ALIGN_CHUNK tells the library to use the bufrsize (see above) as | 
| 1074 |  |     the align parameter. It has nothing to do with the chunking | 
| 1075 |  |     (multidimensional tiling) features of netCDF-4. | 
| 1076 |  |  | 
| 1077 |  |     The file format requires mod 4 alignment, so the align parameters are | 
| 1078 |  |     silently rounded up to multiples of 4. The usual call, | 
| 1079 |  |  | 
| 1080 |  |     \code | 
| 1081 |  |     nc_enddef(ncid); | 
| 1082 |  |     \endcode | 
| 1083 |  |  | 
| 1084 |  |     is equivalent to | 
| 1085 |  |  | 
| 1086 |  |     \code | 
| 1087 |  |     nc__enddef(ncid, 0, 4, 0, 4); | 
| 1088 |  |     \endcode | 
| 1089 |  |  | 
| 1090 |  |     The file format does not contain a "record size" value, this is | 
| 1091 |  |     calculated from the sizes of the record variables. This unfortunate | 
| 1092 |  |     fact prevents us from providing minfree and alignment control of the | 
| 1093 |  |     "records" in a netcdf file. If you add a variable which has an | 
| 1094 |  |     unlimited dimension, the third section will always be copied with the | 
| 1095 |  |     new variable added. | 
| 1096 |  |  | 
| 1097 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1098 |  |     nc_create(). | 
| 1099 |  |  | 
| 1100 |  |     \param h_minfree Sets the pad at the end of the "header" section. | 
| 1101 |  |  | 
| 1102 |  |     \param v_align Controls the alignment of the beginning of the data | 
| 1103 |  |     section for fixed size variables. | 
| 1104 |  |  | 
| 1105 |  |     \param v_minfree Sets the pad at the end of the data section for fixed | 
| 1106 |  |     size variables. | 
| 1107 |  |  | 
| 1108 |  |     \param r_align Controls the alignment of the beginning of the data | 
| 1109 |  |     section for variables which have an unlimited dimension (record | 
| 1110 |  |     variables). | 
| 1111 |  |  | 
| 1112 |  |     \returns ::NC_NOERR No error. | 
| 1113 |  |  | 
| 1114 |  |     \returns ::NC_EBADID Invalid ncid passed. | 
| 1115 |  |  | 
| 1116 |  | */ | 
| 1117 |  | int | 
| 1118 |  | nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, | 
| 1119 |  |            size_t r_align) | 
| 1120 | 0 | { | 
| 1121 | 0 |     NC* ncp; | 
| 1122 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1123 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1124 | 0 |     return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align); | 
| 1125 | 0 | } | 
| 1126 |  |  | 
| 1127 |  | /** \ingroup datasets | 
| 1128 |  |     Synchronize an open netcdf dataset to disk | 
| 1129 |  |  | 
| 1130 |  |     The function nc_sync() offers a way to synchronize the disk copy of a | 
| 1131 |  |     netCDF dataset with in-memory buffers. There are two reasons you might | 
| 1132 |  |     want to synchronize after writes: | 
| 1133 |  |     - To minimize data loss in case of abnormal termination, or | 
| 1134 |  |     - To make data available to other processes for reading immediately | 
| 1135 |  |     after it is written. But note that a process that already had the | 
| 1136 |  |     dataset open for reading would not see the number of records | 
| 1137 |  |     increase when the writing process calls nc_sync(); to accomplish this, | 
| 1138 |  |     the reading process must call nc_sync. | 
| 1139 |  |  | 
| 1140 |  |     This function is backward-compatible with previous versions of the | 
| 1141 |  |     netCDF library. The intent was to allow sharing of a netCDF dataset | 
| 1142 |  |     among multiple readers and one writer, by having the writer call | 
| 1143 |  |     nc_sync() after writing and the readers call nc_sync() before each | 
| 1144 |  |     read. For a writer, this flushes buffers to disk. For a reader, it | 
| 1145 |  |     makes sure that the next read will be from disk rather than from | 
| 1146 |  |     previously cached buffers, so that the reader will see changes made by | 
| 1147 |  |     the writing process (e.g., the number of records written) without | 
| 1148 |  |     having to close and reopen the dataset. If you are only accessing a | 
| 1149 |  |     small amount of data, it can be expensive in computer resources to | 
| 1150 |  |     always synchronize to disk after every write, since you are giving up | 
| 1151 |  |     the benefits of buffering. | 
| 1152 |  |  | 
| 1153 |  |     An easier way to accomplish sharing (and what is now recommended) is | 
| 1154 |  |     to have the writer and readers open the dataset with the NC_SHARE | 
| 1155 |  |     flag, and then it will not be necessary to call nc_sync() at | 
| 1156 |  |     all. However, the nc_sync() function still provides finer granularity | 
| 1157 |  |     than the NC_SHARE flag, if only a few netCDF accesses need to be | 
| 1158 |  |     synchronized among processes. | 
| 1159 |  |  | 
| 1160 |  |     It is important to note that changes to the ancillary data, such as | 
| 1161 |  |     attribute values, are not propagated automatically by use of the | 
| 1162 |  |     NC_SHARE flag. Use of the nc_sync() function is still required for this | 
| 1163 |  |     purpose. | 
| 1164 |  |  | 
| 1165 |  |     Sharing datasets when the writer enters define mode to change the data | 
| 1166 |  |     schema requires extra care. In previous releases, after the writer | 
| 1167 |  |     left define mode, the readers were left looking at an old copy of the | 
| 1168 |  |     dataset, since the changes were made to a new copy. The only way | 
| 1169 |  |     readers could see the changes was by closing and reopening the | 
| 1170 |  |     dataset. Now the changes are made in place, but readers have no | 
| 1171 |  |     knowledge that their internal tables are now inconsistent with the new | 
| 1172 |  |     dataset schema. If netCDF datasets are shared across redefinition, | 
| 1173 |  |     some mechanism external to the netCDF library must be provided that | 
| 1174 |  |     prevents access by readers during redefinition and causes the readers | 
| 1175 |  |     to call nc_sync before any subsequent access. | 
| 1176 |  |  | 
| 1177 |  |     When calling nc_sync(), the netCDF dataset must be in data mode. A | 
| 1178 |  |     netCDF dataset in define mode is synchronized to disk only when | 
| 1179 |  |     nc_enddef() is called. A process that is reading a netCDF dataset that | 
| 1180 |  |     another process is writing may call nc_sync to get updated with the | 
| 1181 |  |     changes made to the data by the writing process (e.g., the number of | 
| 1182 |  |     records written), without having to close and reopen the dataset. | 
| 1183 |  |  | 
| 1184 |  |     Data is automatically synchronized to disk when a netCDF dataset is | 
| 1185 |  |     closed, or whenever you leave define mode. | 
| 1186 |  |  | 
| 1187 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1188 |  |     nc_create(). | 
| 1189 |  |  | 
| 1190 |  |     \returns ::NC_NOERR No error. | 
| 1191 |  |  | 
| 1192 |  |     \returns ::NC_EBADID Invalid ncid passed. | 
| 1193 |  | */ | 
| 1194 |  | int | 
| 1195 |  | nc_sync(int ncid) | 
| 1196 | 0 | { | 
| 1197 | 0 |     NC* ncp; | 
| 1198 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1199 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1200 | 0 |     return ncp->dispatch->sync(ncid); | 
| 1201 | 0 | } | 
| 1202 |  |  | 
| 1203 |  | /** \ingroup datasets | 
| 1204 |  |     No longer necessary for user to invoke manually. | 
| 1205 |  |  | 
| 1206 |  |  | 
| 1207 |  |     \warning Users no longer need to call this function since it is called | 
| 1208 |  |     automatically by nc_close() in case the dataset is in define mode and | 
| 1209 |  |     something goes wrong with committing the changes. The function | 
| 1210 |  |     nc_abort() just closes the netCDF dataset, if not in define mode. If | 
| 1211 |  |     the dataset is being created and is still in define mode, the dataset | 
| 1212 |  |     is deleted. If define mode was entered by a call to nc_redef(), the | 
| 1213 |  |     netCDF dataset is restored to its state before definition mode was | 
| 1214 |  |     entered and the dataset is closed. | 
| 1215 |  |  | 
| 1216 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1217 |  |     nc_create(). | 
| 1218 |  |  | 
| 1219 |  |     \returns ::NC_NOERR No error. | 
| 1220 |  |  | 
| 1221 |  |     <h1>Example</h1> | 
| 1222 |  |  | 
| 1223 |  |     Here is an example using nc_abort to back out of redefinitions of a | 
| 1224 |  |     dataset named foo.nc: | 
| 1225 |  |  | 
| 1226 |  |     \code | 
| 1227 |  |     #include <netcdf.h> | 
| 1228 |  |     ... | 
| 1229 |  |     int ncid, status, latid; | 
| 1230 |  |     ... | 
| 1231 |  |     status = nc_open("foo.nc", NC_WRITE, &ncid); | 
| 1232 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1233 |  |     ... | 
| 1234 |  |     status = nc_redef(ncid); | 
| 1235 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1236 |  |     ... | 
| 1237 |  |     status = nc_def_dim(ncid, "lat", 18L, &latid); | 
| 1238 |  |     if (status != NC_NOERR) { | 
| 1239 |  |     handle_error(status); | 
| 1240 |  |     status = nc_abort(ncid); | 
| 1241 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1242 |  |     } | 
| 1243 |  |     \endcode | 
| 1244 |  |  | 
| 1245 |  | */ | 
| 1246 |  | int | 
| 1247 |  | nc_abort(int ncid) | 
| 1248 | 0 | { | 
| 1249 | 0 |     NC* ncp; | 
| 1250 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1251 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1252 |  |  | 
| 1253 | 0 |     stat = ncp->dispatch->abort(ncid); | 
| 1254 | 0 |     del_from_NCList(ncp); | 
| 1255 | 0 |     free_NC(ncp); | 
| 1256 | 0 |     return stat; | 
| 1257 | 0 | } | 
| 1258 |  |  | 
| 1259 |  | /** \ingroup datasets | 
| 1260 |  |     Close an open netCDF dataset | 
| 1261 |  |  | 
| 1262 |  |     If the dataset in define mode, nc_enddef() will be called before | 
| 1263 |  |     closing. (In this case, if nc_enddef() returns an error, nc_abort() will | 
| 1264 |  |     automatically be called to restore the dataset to the consistent state | 
| 1265 |  |     before define mode was last entered.) After an open netCDF dataset is | 
| 1266 |  |     closed, its netCDF ID may be reassigned to the next netCDF dataset | 
| 1267 |  |     that is opened or created. | 
| 1268 |  |  | 
| 1269 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or nc_create(). | 
| 1270 |  |  | 
| 1271 |  |     \returns ::NC_NOERR No error. | 
| 1272 |  |  | 
| 1273 |  |     \returns ::NC_EBADID Invalid id passed. | 
| 1274 |  |  | 
| 1275 |  |     \returns ::NC_EBADGRPID ncid did not contain the root group id of this | 
| 1276 |  |     file. (NetCDF-4 only). | 
| 1277 |  |  | 
| 1278 |  |     <h1>Example</h1> | 
| 1279 |  |  | 
| 1280 |  |     Here is an example using nc_close to finish the definitions of a new | 
| 1281 |  |     netCDF dataset named foo.nc and release its netCDF ID: | 
| 1282 |  |  | 
| 1283 |  |     \code | 
| 1284 |  |     #include <netcdf.h> | 
| 1285 |  |     ... | 
| 1286 |  |     int status = NC_NOERR; | 
| 1287 |  |     int ncid; | 
| 1288 |  |     ... | 
| 1289 |  |     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); | 
| 1290 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1291 |  |  | 
| 1292 |  |     ...   create dimensions, variables, attributes | 
| 1293 |  |  | 
| 1294 |  |     status = nc_close(ncid); | 
| 1295 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1296 |  |     \endcode | 
| 1297 |  |  | 
| 1298 |  | */ | 
| 1299 |  | int | 
| 1300 |  | nc_close(int ncid) | 
| 1301 | 11 | { | 
| 1302 | 11 |     NC* ncp; | 
| 1303 | 11 |     int stat = NC_check_id(ncid, &ncp); | 
| 1304 | 11 |     if(stat != NC_NOERR) return stat; | 
| 1305 |  |  | 
| 1306 | 11 |     stat = ncp->dispatch->close(ncid,NULL); | 
| 1307 |  |     /* Remove from the nc list */ | 
| 1308 | 11 |     if (!stat) | 
| 1309 | 11 |     { | 
| 1310 | 11 |         del_from_NCList(ncp); | 
| 1311 | 11 |         free_NC(ncp); | 
| 1312 | 11 |     } | 
| 1313 | 11 |     return stat; | 
| 1314 | 11 | } | 
| 1315 |  |  | 
| 1316 |  | /** \ingroup datasets | 
| 1317 |  |     Do a normal close (see nc_close()) on an in-memory dataset, | 
| 1318 |  |     then return a copy of the final memory contents of the dataset. | 
| 1319 |  |  | 
| 1320 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or nc_create(). | 
| 1321 |  |  | 
| 1322 |  |     \param memio a pointer to an NC_memio object into which the final valid memory | 
| 1323 |  |     size and memory will be returned. | 
| 1324 |  |  | 
| 1325 |  |     \returns ::NC_NOERR No error. | 
| 1326 |  |  | 
| 1327 |  |     \returns ::NC_EBADID Invalid id passed. | 
| 1328 |  |  | 
| 1329 |  |     \returns ::NC_ENOMEM Out of memory. | 
| 1330 |  |  | 
| 1331 |  |     \returns ::NC_EDISKLESS if the file was not created as an inmemory file. | 
| 1332 |  |  | 
| 1333 |  |     \returns ::NC_EBADGRPID ncid did not contain the root group id of this | 
| 1334 |  |     file. (NetCDF-4 only). | 
| 1335 |  |  | 
| 1336 |  |     <h1>Example</h1> | 
| 1337 |  |  | 
| 1338 |  |     Here is an example using nc_close_mem to finish the definitions of a new | 
| 1339 |  |     netCDF dataset named foo.nc, return the final memory, | 
| 1340 |  |     and release its netCDF ID: | 
| 1341 |  |  | 
| 1342 |  |     \code | 
| 1343 |  |     #include <netcdf.h> | 
| 1344 |  |     ... | 
| 1345 |  |     int status = NC_NOERR; | 
| 1346 |  |     int ncid; | 
| 1347 |  |     NC_memio finalmem; | 
| 1348 |  |     size_t initialsize = 65000; | 
| 1349 |  |     ... | 
| 1350 |  |     status = nc_create_mem("foo.nc", NC_NOCLOBBER, initialsize, &ncid); | 
| 1351 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1352 |  |     ...   create dimensions, variables, attributes | 
| 1353 |  |     status = nc_close_memio(ncid,&finalmem); | 
| 1354 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1355 |  |     \endcode | 
| 1356 |  |  | 
| 1357 |  | */ | 
| 1358 |  | int | 
| 1359 |  | nc_close_memio(int ncid, NC_memio* memio) | 
| 1360 | 0 | { | 
| 1361 | 0 |     NC* ncp; | 
| 1362 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1363 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1364 |  |  | 
| 1365 | 0 |     stat = ncp->dispatch->close(ncid,memio); | 
| 1366 |  |     /* Remove from the nc list */ | 
| 1367 | 0 |     if (!stat) | 
| 1368 | 0 |     { | 
| 1369 | 0 |         del_from_NCList(ncp); | 
| 1370 | 0 |         free_NC(ncp); | 
| 1371 | 0 |     } | 
| 1372 | 0 |     return stat; | 
| 1373 | 0 | } | 
| 1374 |  |  | 
| 1375 |  | /** \ingroup datasets | 
| 1376 |  |     Change the fill-value mode to improve write performance. | 
| 1377 |  |  | 
| 1378 |  |     This function is intended for advanced usage, to optimize writes under | 
| 1379 |  |     some circumstances described below. The function nc_set_fill() sets the | 
| 1380 |  |     fill mode for a netCDF dataset open for writing and returns the | 
| 1381 |  |     current fill mode in a return parameter. The fill mode can be | 
| 1382 |  |     specified as either ::NC_FILL or ::NC_NOFILL. The default behavior | 
| 1383 |  |     corresponding to ::NC_FILL is that data is pre-filled with fill values, | 
| 1384 |  |     that is fill values are written when you create non-record variables | 
| 1385 |  |     or when you write a value beyond data that has not yet been | 
| 1386 |  |     written. This makes it possible to detect attempts to read data before | 
| 1387 |  |     it was written. For more information on the use of fill values see | 
| 1388 |  |     Fill Values. For information about how to define your own fill values | 
| 1389 |  |     see Attribute Conventions. | 
| 1390 |  |  | 
| 1391 |  |     The behavior corresponding to ::NC_NOFILL overrides the default behavior | 
| 1392 |  |     of prefilling data with fill values. This can be used to enhance | 
| 1393 |  |     performance, because it avoids the duplicate writes that occur when | 
| 1394 |  |     the netCDF library writes fill values that are later overwritten with | 
| 1395 |  |     data. | 
| 1396 |  |  | 
| 1397 |  |     A value indicating which mode the netCDF dataset was already in is | 
| 1398 |  |     returned. You can use this value to temporarily change the fill mode | 
| 1399 |  |     of an open netCDF dataset and then restore it to the previous mode. | 
| 1400 |  |  | 
| 1401 |  |     After you turn on ::NC_NOFILL mode for an open netCDF dataset, you must | 
| 1402 |  |     be certain to write valid data in all the positions that will later be | 
| 1403 |  |     read. Note that nofill mode is only a transient property of a netCDF | 
| 1404 |  |     dataset open for writing: if you close and reopen the dataset, it will | 
| 1405 |  |     revert to the default behavior. You can also revert to the default | 
| 1406 |  |     behavior by calling nc_set_fill() again to explicitly set the fill mode | 
| 1407 |  |     to ::NC_FILL. | 
| 1408 |  |  | 
| 1409 |  |     There are three situations where it is advantageous to set nofill | 
| 1410 |  |     mode: | 
| 1411 |  |     - Creating and initializing a netCDF dataset. In this case, you should | 
| 1412 |  |     set nofill mode before calling nc_enddef() and then write completely | 
| 1413 |  |     all non-record variables and the initial records of all the record | 
| 1414 |  |     variables you want to initialize. | 
| 1415 |  |     - Extending an existing record-oriented netCDF dataset. Set nofill | 
| 1416 |  |     mode after opening the dataset for writing, then append the | 
| 1417 |  |     additional records to the dataset completely, leaving no intervening | 
| 1418 |  |     unwritten records. | 
| 1419 |  |     - Adding new variables that you are going to initialize to an existing | 
| 1420 |  |     netCDF dataset. Set nofill mode before calling nc_enddef() then write | 
| 1421 |  |     all the new variables completely. | 
| 1422 |  |  | 
| 1423 |  |     If the netCDF dataset has an unlimited dimension and the last record | 
| 1424 |  |     was written while in nofill mode, then the dataset may be shorter than | 
| 1425 |  |     if nofill mode was not set, but this will be completely transparent if | 
| 1426 |  |     you access the data only through the netCDF interfaces. | 
| 1427 |  |  | 
| 1428 |  |     The use of this feature may not be available (or even needed) in | 
| 1429 |  |     future releases. Programmers are cautioned against heavy reliance upon | 
| 1430 |  |     this feature. | 
| 1431 |  |  | 
| 1432 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1433 |  |     nc_create(). | 
| 1434 |  |  | 
| 1435 |  |     \param fillmode Desired fill mode for the dataset, either ::NC_NOFILL or | 
| 1436 |  |     ::NC_FILL. | 
| 1437 |  |  | 
| 1438 |  |     \param old_modep Pointer to location for returned current fill mode of | 
| 1439 |  |     the dataset before this call, either ::NC_NOFILL or ::NC_FILL. | 
| 1440 |  |  | 
| 1441 |  |     \returns ::NC_NOERR No error. | 
| 1442 |  |  | 
| 1443 |  |     \returns ::NC_EBADID The specified netCDF ID does not refer to an open | 
| 1444 |  |     netCDF dataset. | 
| 1445 |  |  | 
| 1446 |  |     \returns ::NC_EPERM The specified netCDF ID refers to a dataset open for | 
| 1447 |  |     read-only access. | 
| 1448 |  |  | 
| 1449 |  |     \returns ::NC_EINVAL The fill mode argument is neither ::NC_NOFILL nor | 
| 1450 |  |     ::NC_FILL. | 
| 1451 |  |  | 
| 1452 |  |     <h1>Example</h1> | 
| 1453 |  |  | 
| 1454 |  |     Here is an example using nc_set_fill() to set nofill mode for subsequent | 
| 1455 |  |     writes of a netCDF dataset named foo.nc: | 
| 1456 |  |  | 
| 1457 |  |     \code | 
| 1458 |  |     #include <netcdf.h> | 
| 1459 |  |     ... | 
| 1460 |  |     int ncid, status, old_fill_mode; | 
| 1461 |  |     ... | 
| 1462 |  |     status = nc_open("foo.nc", NC_WRITE, &ncid); | 
| 1463 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1464 |  |  | 
| 1465 |  |     ...     write data with default prefilling behavior | 
| 1466 |  |  | 
| 1467 |  |     status = nc_set_fill(ncid, ::NC_NOFILL, &old_fill_mode); | 
| 1468 |  |     if (status != NC_NOERR) handle_error(status); | 
| 1469 |  |  | 
| 1470 |  |     ...    write data with no prefilling | 
| 1471 |  |     \endcode | 
| 1472 |  | */ | 
| 1473 |  | int | 
| 1474 |  | nc_set_fill(int ncid, int fillmode, int *old_modep) | 
| 1475 | 0 | { | 
| 1476 | 0 |     NC* ncp; | 
| 1477 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1478 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1479 | 0 |     return ncp->dispatch->set_fill(ncid,fillmode,old_modep); | 
| 1480 | 0 | } | 
| 1481 |  |  | 
| 1482 |  | /** | 
| 1483 |  |  * @internal Learn base PE. | 
| 1484 |  |  * | 
| 1485 |  |  * @deprecated This function was used in the old days with the Cray at | 
| 1486 |  |  * NCAR. The Cray is long gone, and this call is now meaningless. The | 
| 1487 |  |  * value returned for pe is always 0. | 
| 1488 |  |  * | 
| 1489 |  |  * @param ncid File and group ID. | 
| 1490 |  |  * @param pe Pointer for base PE. | 
| 1491 |  |  * | 
| 1492 |  |  * @return ::NC_NOERR No error. | 
| 1493 |  |  * @return ::NC_EBADID Invalid ncid passed. | 
| 1494 |  |  * @author Glenn Davis | 
| 1495 |  |  */ | 
| 1496 |  | int | 
| 1497 |  | nc_inq_base_pe(int ncid, int *pe) | 
| 1498 | 0 | { | 
| 1499 | 0 |     NC* ncp; | 
| 1500 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1501 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1502 | 0 |     if (pe) *pe = 0; | 
| 1503 | 0 |     return NC_NOERR; | 
| 1504 | 0 | } | 
| 1505 |  |  | 
| 1506 |  | /** | 
| 1507 |  |  * @internal Sets base processing element (ignored). | 
| 1508 |  |  * | 
| 1509 |  |  * @deprecated This function was used in the old days with the Cray at | 
| 1510 |  |  * NCAR. The Cray is long gone, and this call is supported only for | 
| 1511 |  |  * backward compatibility. | 
| 1512 |  |  * | 
| 1513 |  |  * @param ncid File ID. | 
| 1514 |  |  * @param pe Base PE. | 
| 1515 |  |  * | 
| 1516 |  |  * @return ::NC_NOERR No error. | 
| 1517 |  |  * @return ::NC_EBADID Invalid ncid passed. | 
| 1518 |  |  * @author Glenn Davis | 
| 1519 |  |  */ | 
| 1520 |  | int | 
| 1521 |  | nc_set_base_pe(int ncid, int pe) | 
| 1522 | 0 | { | 
| 1523 | 0 |     NC* ncp; | 
| 1524 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1525 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1526 | 0 |     return NC_NOERR; | 
| 1527 | 0 | } | 
| 1528 |  |  | 
| 1529 |  | /** | 
| 1530 |  |  * @ingroup datasets | 
| 1531 |  |  * Inquire about the binary format of a netCDF file | 
| 1532 |  |  * as presented by the API. | 
| 1533 |  |  * | 
| 1534 |  |  * This function returns the (rarely needed) format version. | 
| 1535 |  |  * | 
| 1536 |  |  * @param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1537 |  |  * nc_create(). | 
| 1538 |  |  * @param formatp Pointer to location for returned format version, one | 
| 1539 |  |  * of NC_FORMAT_CLASSIC, NC_FORMAT_64BIT_OFFSET, NC_FORMAT_CDF5, | 
| 1540 |  |  * NC_FORMAT_NETCDF4, NC_FORMAT_NETCDF4_CLASSIC. | 
| 1541 |  |  * | 
| 1542 |  |  * @returns ::NC_NOERR No error. | 
| 1543 |  |  * @returns ::NC_EBADID Invalid ncid passed. | 
| 1544 |  |  * @author Dennis Heimbigner | 
| 1545 |  |  */ | 
| 1546 |  | int | 
| 1547 |  | nc_inq_format(int ncid, int *formatp) | 
| 1548 | 0 | { | 
| 1549 | 0 |     NC* ncp; | 
| 1550 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1551 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1552 | 0 |     return ncp->dispatch->inq_format(ncid,formatp); | 
| 1553 | 0 | } | 
| 1554 |  |  | 
| 1555 |  | /** \ingroup datasets | 
| 1556 |  |     Obtain more detailed (vis-a-vis nc_inq_format) | 
| 1557 |  |     format information about an open dataset. | 
| 1558 |  |  | 
| 1559 |  |     Note that the netcdf API will present the file | 
| 1560 |  |     as if it had the format specified by nc_inq_format. | 
| 1561 |  |     The true file format, however, may not even be | 
| 1562 |  |     a netcdf file; it might be DAP, HDF4, or PNETCDF, | 
| 1563 |  |     for example. This function returns that true file type. | 
| 1564 |  |     It also returns the effective mode for the file. | 
| 1565 |  |  | 
| 1566 |  |     \param ncid NetCDF ID, from a previous call to nc_open() or | 
| 1567 |  |     nc_create(). | 
| 1568 |  |  | 
| 1569 |  |     \param formatp Pointer to location for returned true format. | 
| 1570 |  |  | 
| 1571 |  |     \param modep Pointer to location for returned mode flags. | 
| 1572 |  |  | 
| 1573 |  |     Refer to the actual list in the file netcdf.h to see the | 
| 1574 |  |     currently defined set. | 
| 1575 |  |  | 
| 1576 |  |     \returns ::NC_NOERR No error. | 
| 1577 |  |  | 
| 1578 |  |     \returns ::NC_EBADID Invalid ncid passed. | 
| 1579 |  |  | 
| 1580 |  | */ | 
| 1581 |  | int | 
| 1582 |  | nc_inq_format_extended(int ncid, int *formatp, int *modep) | 
| 1583 | 0 | { | 
| 1584 | 0 |     NC* ncp; | 
| 1585 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1586 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1587 | 0 |     return ncp->dispatch->inq_format_extended(ncid,formatp,modep); | 
| 1588 | 0 | } | 
| 1589 |  |  | 
| 1590 |  | /**\ingroup datasets | 
| 1591 |  |    Inquire about a file or group. | 
| 1592 |  |  | 
| 1593 |  |    \param ncid NetCDF or group ID, from a previous call to nc_open(), | 
| 1594 |  |    nc_create(), nc_def_grp(), or associated inquiry functions such as | 
| 1595 |  |    nc_inq_ncid(). | 
| 1596 |  |  | 
| 1597 |  |    \param ndimsp Pointer to location for returned number of dimensions | 
| 1598 |  |    defined for this netCDF dataset. Ignored if NULL. | 
| 1599 |  |  | 
| 1600 |  |    \param nvarsp Pointer to location for returned number of variables | 
| 1601 |  |    defined for this netCDF dataset. Ignored if NULL. | 
| 1602 |  |  | 
| 1603 |  |    \param nattsp Pointer to location for returned number of global | 
| 1604 |  |    attributes defined for this netCDF dataset. Ignored if NULL. | 
| 1605 |  |  | 
| 1606 |  |    \param unlimdimidp Pointer to location for returned ID of the | 
| 1607 |  |    unlimited dimension, if there is one for this netCDF dataset. If no | 
| 1608 |  |    unlimited length dimension has been defined, -1 is returned. Ignored | 
| 1609 |  |    if NULL.  If there are multiple unlimited dimensions (possible only | 
| 1610 |  |    for netCDF-4 files), only a pointer to the first is returned, for | 
| 1611 |  |    backward compatibility.  If you want them all, use nc_inq_unlimids(). | 
| 1612 |  |  | 
| 1613 |  |    \returns ::NC_NOERR No error. | 
| 1614 |  |  | 
| 1615 |  |    \returns ::NC_EBADID Invalid ncid passed. | 
| 1616 |  |  | 
| 1617 |  |    <h1>Example</h1> | 
| 1618 |  |  | 
| 1619 |  |    Here is an example using nc_inq to find out about a netCDF dataset | 
| 1620 |  |    named foo.nc: | 
| 1621 |  |  | 
| 1622 |  |    \code | 
| 1623 |  |    #include <netcdf.h> | 
| 1624 |  |    ... | 
| 1625 |  |    int status, ncid, ndims, nvars, ngatts, unlimdimid; | 
| 1626 |  |    ... | 
| 1627 |  |    status = nc_open("foo.nc", NC_NOWRITE, &ncid); | 
| 1628 |  |    if (status != NC_NOERR) handle_error(status); | 
| 1629 |  |    ... | 
| 1630 |  |    status = nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid); | 
| 1631 |  |    if (status != NC_NOERR) handle_error(status); | 
| 1632 |  |    \endcode | 
| 1633 |  | */ | 
| 1634 |  | int | 
| 1635 |  | nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp) | 
| 1636 | 0 | { | 
| 1637 | 0 |     NC* ncp; | 
| 1638 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1639 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1640 | 0 |     return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp); | 
| 1641 | 0 | } | 
| 1642 |  |  | 
| 1643 |  | /** | 
| 1644 |  |  * Learn the number of variables in a file or group. | 
| 1645 |  |  * | 
| 1646 |  |  * @param ncid File and group ID. | 
| 1647 |  |  * @param nvarsp Pointer that gets number of variables. Ignored if NULL. | 
| 1648 |  |  * | 
| 1649 |  |  * @return ::NC_NOERR No error. | 
| 1650 |  |  * @return ::NC_EBADID Bad ncid. | 
| 1651 |  |  * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner | 
| 1652 |  |  */ | 
| 1653 |  | int | 
| 1654 |  | nc_inq_nvars(int ncid, int *nvarsp) | 
| 1655 | 0 | { | 
| 1656 | 0 |     NC* ncp; | 
| 1657 | 0 |     int stat = NC_check_id(ncid, &ncp); | 
| 1658 | 0 |     if(stat != NC_NOERR) return stat; | 
| 1659 | 0 |     return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL); | 
| 1660 | 0 | } | 
| 1661 |  |  | 
| 1662 |  | /**\ingroup datasets | 
| 1663 |  |    Inquire about a type. | 
| 1664 |  |  | 
| 1665 |  |    Given an ncid and a typeid, get the information about a type. This | 
| 1666 |  |    function will work on any type, including atomic and any user defined | 
| 1667 |  |    type, whether compound, opaque, enumeration, or variable length array. | 
| 1668 |  |  | 
| 1669 |  |    For even more information about a user defined type nc_inq_user_type(). | 
| 1670 |  |  | 
| 1671 |  |    \param ncid The ncid for the group containing the type (ignored for | 
| 1672 |  |    atomic types). | 
| 1673 |  |  | 
| 1674 |  |    \param xtype The typeid for this type, as returned by nc_def_compound, | 
| 1675 |  |    nc_def_opaque, nc_def_enum, nc_def_vlen, or nc_inq_var, or as found in | 
| 1676 |  |    netcdf.h in the list of atomic types (NC_CHAR, NC_INT, etc.). | 
| 1677 |  |  | 
| 1678 |  |    \param name If non-NULL, the name of the user defined type will be | 
| 1679 |  |    copied here. It will be NC_MAX_NAME bytes or less. For atomic types, | 
| 1680 |  |    the type name from CDL will be given. | 
| 1681 |  |  | 
| 1682 |  |    \param size If non-NULL, the (in-memory) size of the type in bytes | 
| 1683 |  |    will be copied here. VLEN type size is the size of nc_vlen_t. String | 
| 1684 |  |    size is returned as the size of a character pointer. The size may be | 
| 1685 |  |    used to malloc space for the data, no matter what the type. | 
| 1686 |  |  | 
| 1687 |  |    \returns ::NC_NOERR No error. | 
| 1688 |  |  | 
| 1689 |  |    \returns ::NC_EBADTYPE Bad typeid. | 
| 1690 |  |  | 
| 1691 |  |    \returns ::NC_ENOTNC4 Seeking a user-defined type in a netCDF-3 file. | 
| 1692 |  |  | 
| 1693 |  |    \returns ::NC_ESTRICTNC3 Seeking a user-defined type in a netCDF-4 file | 
| 1694 |  |    for which classic model has been turned on. | 
| 1695 |  |  | 
| 1696 |  |    \returns ::NC_EBADGRPID Bad group ID in ncid. | 
| 1697 |  |  | 
| 1698 |  |    \returns ::NC_EBADID Type ID not found. | 
| 1699 |  |  | 
| 1700 |  |    \returns ::NC_EHDFERR An error was reported by the HDF5 layer. | 
| 1701 |  |  | 
| 1702 |  |    <h1>Example</h1> | 
| 1703 |  |  | 
| 1704 |  |    This example is from the test program tst_enums.c, and it uses all the | 
| 1705 |  |    possible inquiry functions on an enum type. | 
| 1706 |  |  | 
| 1707 |  |    \code | 
| 1708 |  |    if (nc_inq_user_type(ncid, typeids[0], name_in, &base_size_in, &base_nc_type_in, | 
| 1709 |  |    &nfields_in, &class_in)) ERR; | 
| 1710 |  |    if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int) || | 
| 1711 |  |    base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR; | 
| 1712 |  |    if (nc_inq_type(ncid, typeids[0], name_in, &base_size_in)) ERR; | 
| 1713 |  |    if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int)) ERR; | 
| 1714 |  |    if (nc_inq_enum(ncid, typeids[0], name_in, &base_nc_type, &base_size_in, &num_members)) ERR; | 
| 1715 |  |    if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT || num_members != NUM_MEMBERS) ERR; | 
| 1716 |  |    for (i = 0; i < NUM_MEMBERS; i++) | 
| 1717 |  |    { | 
| 1718 |  |    if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR; | 
| 1719 |  |    if (strcmp(name_in, member_name[i]) || value_in != member_value[i]) ERR; | 
| 1720 |  |    if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR; | 
| 1721 |  |    if (strcmp(name_in, member_name[i])) ERR; | 
| 1722 |  |    } | 
| 1723 |  |  | 
| 1724 |  |    if (nc_close(ncid)) ERR; | 
| 1725 |  |    \endcode | 
| 1726 |  | */ | 
| 1727 |  | int | 
| 1728 |  | nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size) | 
| 1729 | 0 | { | 
| 1730 | 0 |     NC* ncp; | 
| 1731 | 0 |     int stat; | 
| 1732 |  |  | 
| 1733 |  |     /* Do a quick triage on xtype */ | 
| 1734 | 0 |     if(xtype <= NC_NAT) return NC_EBADTYPE; | 
| 1735 |  |     /* For compatibility, we need to allow inq about | 
| 1736 |  |        atomic types, even if ncid is ill-defined */ | 
| 1737 | 0 |     if(xtype <= ATOMICTYPEMAX4) { | 
| 1738 | 0 |         if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME); | 
| 1739 | 0 |         if(size) *size = NC_atomictypelen(xtype); | 
| 1740 | 0 |         return NC_NOERR; | 
| 1741 | 0 |     } | 
| 1742 |  |     /* Apparently asking about a user defined type, so we need | 
| 1743 |  |        a valid ncid */ | 
| 1744 | 0 |     stat = NC_check_id(ncid, &ncp); | 
| 1745 | 0 |     if(stat != NC_NOERR) /* bad ncid */ | 
| 1746 | 0 |         return NC_EBADTYPE; | 
| 1747 |  |     /* have good ncid */ | 
| 1748 | 0 |     return ncp->dispatch->inq_type(ncid,xtype,name,size); | 
| 1749 | 0 | } | 
| 1750 |  |  | 
| 1751 |  | /** \defgroup dispatch dispatch functions. */ | 
| 1752 |  | /** \{ | 
| 1753 |  |  | 
| 1754 |  | \ingroup dispatch | 
| 1755 |  | */ | 
| 1756 |  |  | 
| 1757 |  |  | 
| 1758 |  | /** | 
| 1759 |  |    Check the create mode parameter for sanity. | 
| 1760 |  |  | 
| 1761 |  |    Some create flags cannot be used if corresponding library features are | 
| 1762 |  |    enabled during the build. This function does a pre-check of the mode | 
| 1763 |  |    flag before calling the dispatch layer nc_create functions. | 
| 1764 |  |  | 
| 1765 |  |    \param mode The creation mode flag. | 
| 1766 |  |  | 
| 1767 |  |    \returns ::NC_NOERR No error. | 
| 1768 |  |    \returns ::NC_ENOTBUILT Requested feature not built into library | 
| 1769 |  |    \returns ::NC_EINVAL Invalid combination of modes. | 
| 1770 |  |    \internal | 
| 1771 |  |    \ingroup dispatch | 
| 1772 |  |    \author Ed Hartnett | 
| 1773 |  | */ | 
| 1774 |  | static int | 
| 1775 |  | check_create_mode(int mode) | 
| 1776 | 0 | { | 
| 1777 | 0 |     int mode_format; | 
| 1778 | 0 |     int use_mmap = 0; | 
| 1779 | 0 |     int inmemory = 0; | 
| 1780 | 0 |     int diskless = 0; | 
| 1781 |  |  | 
| 1782 |  |     /* This is a clever check to see if more than one format bit is | 
| 1783 |  |      * set. */ | 
| 1784 | 0 |     mode_format = (mode & NC_NETCDF4) | (mode & NC_64BIT_OFFSET) | | 
| 1785 | 0 |         (mode & NC_CDF5); | 
| 1786 | 0 |     if (mode_format && (mode_format & (mode_format - 1))) | 
| 1787 | 0 |         return NC_EINVAL; | 
| 1788 |  |  | 
| 1789 | 0 |     use_mmap = ((mode & NC_MMAP) == NC_MMAP); | 
| 1790 | 0 |     inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY); | 
| 1791 | 0 |     diskless = ((mode & NC_DISKLESS) == NC_DISKLESS); | 
| 1792 |  |  | 
| 1793 |  |     /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */ | 
| 1794 | 0 |     if(diskless && inmemory) return NC_EDISKLESS; | 
| 1795 | 0 |     if(diskless && use_mmap) return NC_EDISKLESS; | 
| 1796 | 0 |     if(inmemory && use_mmap) return NC_EINMEMORY; | 
| 1797 |  |  | 
| 1798 |  |     /* mmap is not allowed for netcdf-4 */ | 
| 1799 | 0 |     if(use_mmap && (mode & NC_NETCDF4)) return NC_EINVAL; | 
| 1800 |  |  | 
| 1801 |  | #ifndef USE_NETCDF4 | 
| 1802 |  |     /* If the user asks for a netCDF-4 file, and the library was built | 
| 1803 |  |      * without netCDF-4, then return an error.*/ | 
| 1804 |  |     if (mode & NC_NETCDF4) | 
| 1805 |  |         return NC_ENOTBUILT; | 
| 1806 |  | #endif /* USE_NETCDF4 undefined */ | 
| 1807 |  |  | 
| 1808 |  |     /* Well I guess there is some sanity in the world after all. */ | 
| 1809 | 0 |     return NC_NOERR; | 
| 1810 | 0 | } | 
| 1811 |  |  | 
| 1812 |  | /** | 
| 1813 |  |  * @internal Create a file, calling the appropriate dispatch create | 
| 1814 |  |  * call. | 
| 1815 |  |  * | 
| 1816 |  |  * For create, we have the following pieces of information to use to | 
| 1817 |  |  * determine the dispatch table: | 
| 1818 |  |  * - path | 
| 1819 |  |  * - cmode | 
| 1820 |  |  * | 
| 1821 |  |  * @param path0 The file name of the new netCDF dataset. | 
| 1822 |  |  * @param cmode The creation mode flag, the same as in nc_create(). | 
| 1823 |  |  * @param initialsz This parameter sets the initial size of the file | 
| 1824 |  |  * at creation time. This only applies to classic | 
| 1825 |  |  * files. | 
| 1826 |  |  * @param basepe Deprecated parameter from the Cray days. | 
| 1827 |  |  * @param chunksizehintp A pointer to the chunk size hint. This only | 
| 1828 |  |  * applies to classic files. | 
| 1829 |  |  * @param useparallel Non-zero if parallel I/O is to be used on this | 
| 1830 |  |  * file. | 
| 1831 |  |  * @param parameters Pointer to MPI comm and info. | 
| 1832 |  |  * @param ncidp Pointer to location where returned netCDF ID is to be | 
| 1833 |  |  * stored. | 
| 1834 |  |  * | 
| 1835 |  |  * @returns ::NC_NOERR No error. | 
| 1836 |  |  * @ingroup dispatch | 
| 1837 |  |  * @author Dennis Heimbigner, Ed Hartnett, Ward Fisher | 
| 1838 |  |  */ | 
| 1839 |  | int | 
| 1840 |  | NC_create(const char *path0, int cmode, size_t initialsz, | 
| 1841 |  |           int basepe, size_t *chunksizehintp, int useparallel, | 
| 1842 |  |           void* parameters, int *ncidp) | 
| 1843 | 0 | { | 
| 1844 | 0 |     int stat = NC_NOERR; | 
| 1845 | 0 |     NC* ncp = NULL; | 
| 1846 | 0 |     const NC_Dispatch* dispatcher = NULL; | 
| 1847 | 0 |     char* path = NULL; | 
| 1848 | 0 |     NCmodel model; | 
| 1849 | 0 |     char* newpath = NULL; | 
| 1850 |  | 
 | 
| 1851 | 0 |     TRACE(nc_create); | 
| 1852 | 0 |     if(path0 == NULL) | 
| 1853 | 0 |         {stat = NC_EINVAL; goto done;} | 
| 1854 |  |  | 
| 1855 |  |     /* Check mode flag for sanity. */ | 
| 1856 | 0 |     if ((stat = check_create_mode(cmode))) goto done; | 
| 1857 |  |  | 
| 1858 |  |     /* Initialize the library. The available dispatch tables | 
| 1859 |  |      * will depend on how netCDF was built | 
| 1860 |  |      * (with/without netCDF-4, DAP, CDMREMOTE). */ | 
| 1861 | 0 |     if(!NC_initialized) { | 
| 1862 | 0 |         if ((stat = nc_initialize())) goto done; | 
| 1863 | 0 |     } | 
| 1864 |  |  | 
| 1865 | 0 |     { | 
| 1866 |  |         /* Skip past any leading whitespace in path */ | 
| 1867 | 0 |         const unsigned char* p; | 
| 1868 | 0 |         for(p=(const unsigned char*)path0;*p;p++) {if(*p > ' ') break;} | 
| 1869 | 0 |         path = nulldup((const char*)p); | 
| 1870 | 0 |     } | 
| 1871 |  | 
 | 
| 1872 | 0 |     memset(&model,0,sizeof(model)); | 
| 1873 | 0 |     newpath = NULL; | 
| 1874 | 0 |     if((stat = NC_infermodel(path,&cmode,1,useparallel,NULL,&model,&newpath))) goto done; | 
| 1875 | 0 |     if(newpath) { | 
| 1876 | 0 |         nullfree(path); | 
| 1877 | 0 |         path = newpath; | 
| 1878 | 0 |         newpath = NULL; | 
| 1879 | 0 |     } | 
| 1880 |  | 
 | 
| 1881 | 0 |     assert(model.format != 0 && model.impl != 0); | 
| 1882 |  |  | 
| 1883 |  |     /* Now, check for NC_ENOTBUILT cases limited to create (so e.g. HDF4 is not listed) */ | 
| 1884 | 0 | #ifndef USE_HDF5 | 
| 1885 | 0 |     if (model.impl == NC_FORMATX_NC4) | 
| 1886 | 0 |     {stat = NC_ENOTBUILT; goto done;} | 
| 1887 | 0 | #endif | 
| 1888 | 0 | #ifndef USE_PNETCDF | 
| 1889 | 0 |     if (model.impl == NC_FORMATX_PNETCDF) | 
| 1890 | 0 |     {stat = NC_ENOTBUILT; goto done;} | 
| 1891 | 0 | #endif | 
| 1892 |  | #ifndef NETCDF_ENABLE_CDF5 | 
| 1893 |  |     if (model.impl == NC_FORMATX_NC3 && (cmode & NC_64BIT_DATA)) | 
| 1894 |  |     {stat = NC_ENOTBUILT; goto done;} | 
| 1895 |  | #endif | 
| 1896 |  |  | 
| 1897 |  |     /* Figure out what dispatcher to use */ | 
| 1898 | 0 |     switch (model.impl) { | 
| 1899 |  | #ifdef USE_HDF5 | 
| 1900 |  |     case NC_FORMATX_NC4: | 
| 1901 |  |         dispatcher = HDF5_dispatch_table; | 
| 1902 |  |         break; | 
| 1903 |  | #endif | 
| 1904 |  | #ifdef USE_PNETCDF | 
| 1905 |  |     case NC_FORMATX_PNETCDF: | 
| 1906 |  |         dispatcher = NCP_dispatch_table; | 
| 1907 |  |         break; | 
| 1908 |  | #endif | 
| 1909 | 0 | #ifdef USE_NETCDF4 | 
| 1910 | 0 |     case NC_FORMATX_UDF0: | 
| 1911 | 0 |         dispatcher = UDF0_dispatch_table; | 
| 1912 | 0 |         break; | 
| 1913 | 0 |     case NC_FORMATX_UDF1: | 
| 1914 | 0 |         dispatcher = UDF1_dispatch_table; | 
| 1915 | 0 |         break; | 
| 1916 | 0 | #endif /* USE_NETCDF4 */ | 
| 1917 | 0 | #ifdef NETCDF_ENABLE_NCZARR | 
| 1918 | 0 |     case NC_FORMATX_NCZARR: | 
| 1919 | 0 |         dispatcher = NCZ_dispatch_table; | 
| 1920 | 0 |   break; | 
| 1921 | 0 | #endif | 
| 1922 | 0 |     case NC_FORMATX_NC3: | 
| 1923 | 0 |         dispatcher = NC3_dispatch_table; | 
| 1924 | 0 |         break; | 
| 1925 | 0 |     default: | 
| 1926 | 0 |         {stat = NC_ENOTNC; goto done;} | 
| 1927 | 0 |     } | 
| 1928 |  |  | 
| 1929 |  |     /* Create the NC* instance and insert its dispatcher and model */ | 
| 1930 | 0 |     if((stat = new_NC(dispatcher,path,cmode,&ncp))) goto done; | 
| 1931 |  |  | 
| 1932 |  |     /* Add to list of known open files and define ext_ncid */ | 
| 1933 | 0 |     add_to_NCList(ncp); | 
| 1934 |  |  | 
| 1935 |  |     /* Assume create will fill in remaining ncp fields */ | 
| 1936 | 0 |     if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp, | 
| 1937 | 0 |                                    parameters, dispatcher, ncp->ext_ncid))) { | 
| 1938 | 0 |         del_from_NCList(ncp); /* oh well */ | 
| 1939 | 0 |         free_NC(ncp); | 
| 1940 | 0 |     } else { | 
| 1941 | 0 |         if(ncidp)*ncidp = ncp->ext_ncid; | 
| 1942 | 0 |     } | 
| 1943 | 0 | done: | 
| 1944 | 0 |     nullfree(path); | 
| 1945 | 0 |     nullfree(newpath); | 
| 1946 | 0 |     return stat; | 
| 1947 | 0 | } | 
| 1948 |  |  | 
| 1949 |  | /** | 
| 1950 |  |  * @internal Open a netCDF file (or remote dataset) calling the | 
| 1951 |  |  * appropriate dispatch function. | 
| 1952 |  |  * | 
| 1953 |  |  * For open, we have the following pieces of information to use to | 
| 1954 |  |  * determine the dispatch table. | 
| 1955 |  |  * - table specified by override | 
| 1956 |  |  * - path | 
| 1957 |  |  * - omode | 
| 1958 |  |  * - the contents of the file (if it exists), basically checking its magic number. | 
| 1959 |  |  * | 
| 1960 |  |  * @param path0 Path to the file to open. | 
| 1961 |  |  * @param omode Open mode. | 
| 1962 |  |  * @param basepe Base processing element (ignored). | 
| 1963 |  |  * @param chunksizehintp Size hint for classic files. | 
| 1964 |  |  * @param useparallel If true use parallel I/O. | 
| 1965 |  |  * @param parameters Extra parameters for the open. | 
| 1966 |  |  * @param ncidp Pointer that gets ncid. | 
| 1967 |  |  * | 
| 1968 |  |  * @returns ::NC_NOERR No error. | 
| 1969 |  |  * @ingroup dispatch | 
| 1970 |  |  * @author Dennis Heimbigner | 
| 1971 |  |  */ | 
| 1972 |  | int | 
| 1973 |  | NC_open(const char *path0, int omode, int basepe, size_t *chunksizehintp, | 
| 1974 |  |         int useparallel, void* parameters, int *ncidp) | 
| 1975 | 339 | { | 
| 1976 | 339 |     int stat = NC_NOERR; | 
| 1977 | 339 |     NC* ncp = NULL; | 
| 1978 | 339 |     const NC_Dispatch* dispatcher = NULL; | 
| 1979 | 339 |     int inmemory = 0; | 
| 1980 | 339 |     int diskless = 0; | 
| 1981 | 339 |     int use_mmap = 0; | 
| 1982 | 339 |     char* path = NULL; | 
| 1983 | 339 |     NCmodel model; | 
| 1984 | 339 |     char* newpath = NULL; | 
| 1985 |  |  | 
| 1986 | 339 |     TRACE(nc_open); | 
| 1987 | 339 |     if(!NC_initialized) { | 
| 1988 | 1 |         stat = nc_initialize(); | 
| 1989 | 1 |         if(stat) goto done; | 
| 1990 | 1 |     } | 
| 1991 |  |  | 
| 1992 |  |     /* Check inputs. */ | 
| 1993 | 339 |     if (!path0) | 
| 1994 | 0 |         {stat = NC_EINVAL; goto done;} | 
| 1995 |  |  | 
| 1996 |  |     /* Capture the inmemory related flags */ | 
| 1997 | 339 |     use_mmap = ((omode & NC_MMAP) == NC_MMAP); | 
| 1998 | 339 |     diskless = ((omode & NC_DISKLESS) == NC_DISKLESS); | 
| 1999 | 339 |     inmemory = ((omode & NC_INMEMORY) == NC_INMEMORY); | 
| 2000 |  |  | 
| 2001 |  |     /* NC_INMEMORY and NC_DISKLESS and NC_MMAP are all mutually exclusive */ | 
| 2002 | 339 |     if(diskless && inmemory) {stat = NC_EDISKLESS; goto done;} | 
| 2003 | 339 |     if(diskless && use_mmap) {stat = NC_EDISKLESS; goto done;} | 
| 2004 | 339 |     if(inmemory && use_mmap) {stat = NC_EINMEMORY; goto done;} | 
| 2005 |  |  | 
| 2006 |  |     /* mmap is not allowed for netcdf-4 */ | 
| 2007 | 339 |     if(use_mmap && (omode & NC_NETCDF4)) {stat = NC_EINVAL; goto done;} | 
| 2008 |  |  | 
| 2009 |  |     /* Attempt to do file path conversion: note that this will do | 
| 2010 |  |        nothing if path is a 'file:...' url, so it will need to be | 
| 2011 |  |        repeated in protocol code (e.g. libdap2, libdap4, etc). | 
| 2012 |  |     */ | 
| 2013 |  |  | 
| 2014 | 339 |     { | 
| 2015 |  |         /* Skip past any leading whitespace in path */ | 
| 2016 | 339 |         const char* p; | 
| 2017 | 339 |         for(p=(const char*)path0;*p;p++) {if(*p < 0 || *p > ' ') break;} | 
| 2018 | 339 |         path = nulldup(p); | 
| 2019 | 339 |     } | 
| 2020 |  |  | 
| 2021 | 339 |     memset(&model,0,sizeof(model)); | 
| 2022 |  |     /* Infer model implementation and format, possibly by reading the file */ | 
| 2023 | 339 |     if((stat = NC_infermodel(path,&omode,0,useparallel,parameters,&model,&newpath))) | 
| 2024 | 48 |         goto done; | 
| 2025 | 291 |     if(newpath) { | 
| 2026 | 0 |         nullfree(path); | 
| 2027 | 0 |         path = newpath; | 
| 2028 | 0 |   newpath = NULL; | 
| 2029 | 0 |     } | 
| 2030 |  |  | 
| 2031 |  |     /* Still no implementation, give up */ | 
| 2032 | 291 |     if(model.impl == 0) { | 
| 2033 |  | #ifdef DEBUG | 
| 2034 |  |         fprintf(stderr,"implementation == 0\n"); | 
| 2035 |  | #endif | 
| 2036 | 0 |         {stat = NC_ENOTNC; goto done;} | 
| 2037 | 0 |     } | 
| 2038 |  |  | 
| 2039 |  |     /* Suppress unsupported formats */ | 
| 2040 |  | #if 0 | 
| 2041 |  |     /* (should be more compact, table-driven, way to do this) */ | 
| 2042 |  |     { | 
| 2043 |  |   int hdf5built = 0; | 
| 2044 |  |   int hdf4built = 0; | 
| 2045 |  |   int cdf5built = 0; | 
| 2046 |  |   int udf0built = 0; | 
| 2047 |  |   int udf1built = 0; | 
| 2048 |  |   int nczarrbuilt = 0; | 
| 2049 |  | #ifdef USE_NETCDF4 | 
| 2050 |  |         hdf5built = 1; | 
| 2051 |  | #endif | 
| 2052 |  | #ifdef USE_HDF4 | 
| 2053 |  |         hdf4built = 1; | 
| 2054 |  | #endif | 
| 2055 |  | #ifdef NETCDF_ENABLE_CDF5 | 
| 2056 |  |         cdf5built = 1; | 
| 2057 |  | #endif | 
| 2058 |  | #ifdef NETCDF_ENABLE_NCZARR | 
| 2059 |  |   nczarrbuilt = 1; | 
| 2060 |  | #endif | 
| 2061 |  |         if(UDF0_dispatch_table != NULL) | 
| 2062 |  |             udf0built = 1; | 
| 2063 |  |         if(UDF1_dispatch_table != NULL) | 
| 2064 |  |             udf1built = 1; | 
| 2065 |  |  | 
| 2066 |  |         if(!hdf5built && model.impl == NC_FORMATX_NC4) | 
| 2067 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2068 |  |         if(!hdf4built && model.impl == NC_FORMATX_NC_HDF4) | 
| 2069 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2070 |  |         if(!cdf5built && model.impl == NC_FORMATX_NC3 && model.format == NC_FORMAT_CDF5) | 
| 2071 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2072 |  |   if(!nczarrbuilt && model.impl == NC_FORMATX_NCZARR) | 
| 2073 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2074 |  |         if(!udf0built && model.impl == NC_FORMATX_UDF0) | 
| 2075 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2076 |  |         if(!udf1built && model.impl == NC_FORMATX_UDF1) | 
| 2077 |  |         {stat = NC_ENOTBUILT; goto done;} | 
| 2078 |  |     } | 
| 2079 |  | #else | 
| 2080 | 291 |     { | 
| 2081 | 291 |   unsigned built = 0 /* leave off the trailing semicolon so we can build constant */ | 
| 2082 | 291 |     | (1<<NC_FORMATX_NC3) /* NC3 always supported */ | 
| 2083 |  | #ifdef USE_HDF5 | 
| 2084 |  |     | (1<<NC_FORMATX_NC_HDF5) | 
| 2085 |  | #endif | 
| 2086 |  | #ifdef USE_HDF4 | 
| 2087 |  |     | (1<<NC_FORMATX_NC_HDF4) | 
| 2088 |  | #endif | 
| 2089 | 291 | #ifdef NETCDF_ENABLE_NCZARR | 
| 2090 | 291 |     | (1<<NC_FORMATX_NCZARR) | 
| 2091 | 291 | #endif | 
| 2092 |  | #ifdef NETCDF_ENABLE_DAP | 
| 2093 |  |     | (1<<NC_FORMATX_DAP2) | 
| 2094 |  | #endif | 
| 2095 |  | #ifdef NETCDF_ENABLE_DAP4 | 
| 2096 |  |     | (1<<NC_FORMATX_DAP4) | 
| 2097 |  | #endif | 
| 2098 |  | #ifdef USE_PNETCDF | 
| 2099 |  |     | (1<<NC_FORMATX_PNETCDF) | 
| 2100 |  | #endif | 
| 2101 | 291 |     ; /* end of the built flags */ | 
| 2102 | 291 |         if(UDF0_dispatch_table != NULL) | 
| 2103 | 0 |       built |= (1<<NC_FORMATX_UDF0); | 
| 2104 | 291 |         if(UDF1_dispatch_table != NULL) | 
| 2105 | 0 |       built |= (1<<NC_FORMATX_UDF1); | 
| 2106 |  |   /* Verify */ | 
| 2107 | 291 |   if((built & (1 << model.impl)) == 0) | 
| 2108 | 0 |             {stat = NC_ENOTBUILT; goto done;} | 
| 2109 |  | #ifndef NETCDF_ENABLE_CDF5 | 
| 2110 |  |   /* Special case because there is no separate CDF5 dispatcher */ | 
| 2111 |  |         if(model.impl == NC_FORMATX_NC3 && (omode & NC_64BIT_DATA)) | 
| 2112 |  |             {stat = NC_ENOTBUILT; goto done;} | 
| 2113 |  | #endif | 
| 2114 | 291 |     } | 
| 2115 | 291 | #endif | 
| 2116 |  |     /* Figure out what dispatcher to use */ | 
| 2117 | 291 |     if (!dispatcher) { | 
| 2118 | 291 |         switch (model.impl) { | 
| 2119 |  | #ifdef NETCDF_ENABLE_DAP | 
| 2120 |  |         case NC_FORMATX_DAP2: | 
| 2121 |  |             dispatcher = NCD2_dispatch_table; | 
| 2122 |  |             break; | 
| 2123 |  | #endif | 
| 2124 |  | #ifdef NETCDF_ENABLE_DAP4 | 
| 2125 |  |         case NC_FORMATX_DAP4: | 
| 2126 |  |             dispatcher = NCD4_dispatch_table; | 
| 2127 |  |             break; | 
| 2128 |  | #endif | 
| 2129 | 0 | #ifdef NETCDF_ENABLE_NCZARR | 
| 2130 | 0 |   case NC_FORMATX_NCZARR: | 
| 2131 | 0 |       dispatcher = NCZ_dispatch_table; | 
| 2132 | 0 |       break; | 
| 2133 | 0 | #endif | 
| 2134 |  | #ifdef USE_PNETCDF | 
| 2135 |  |         case NC_FORMATX_PNETCDF: | 
| 2136 |  |             dispatcher = NCP_dispatch_table; | 
| 2137 |  |             break; | 
| 2138 |  | #endif | 
| 2139 |  | #ifdef USE_HDF5 | 
| 2140 |  |         case NC_FORMATX_NC4: | 
| 2141 |  |             dispatcher = HDF5_dispatch_table; | 
| 2142 |  |             break; | 
| 2143 |  | #endif | 
| 2144 |  | #ifdef USE_HDF4 | 
| 2145 |  |         case NC_FORMATX_NC_HDF4: | 
| 2146 |  |             dispatcher = HDF4_dispatch_table; | 
| 2147 |  |             break; | 
| 2148 |  | #endif | 
| 2149 | 0 | #ifdef USE_NETCDF4 | 
| 2150 | 0 |         case NC_FORMATX_UDF0: | 
| 2151 | 0 |             dispatcher = UDF0_dispatch_table; | 
| 2152 | 0 |             break; | 
| 2153 | 0 |         case NC_FORMATX_UDF1: | 
| 2154 | 0 |             dispatcher = UDF1_dispatch_table; | 
| 2155 | 0 |             break; | 
| 2156 | 0 | #endif /* USE_NETCDF4 */ | 
| 2157 | 291 |         case NC_FORMATX_NC3: | 
| 2158 | 291 |             dispatcher = NC3_dispatch_table; | 
| 2159 | 291 |             break; | 
| 2160 | 0 |         default: | 
| 2161 | 0 |             stat = NC_ENOTNC; | 
| 2162 | 0 |       goto done; | 
| 2163 | 291 |         } | 
| 2164 | 291 |     } | 
| 2165 |  |  | 
| 2166 |  |  | 
| 2167 |  |     /* If we can't figure out what dispatch table to use, give up. */ | 
| 2168 | 291 |     if (!dispatcher) {stat = NC_ENOTNC; goto done;} | 
| 2169 |  |  | 
| 2170 |  |     /* Create the NC* instance and insert its dispatcher */ | 
| 2171 | 291 |     if((stat = new_NC(dispatcher,path,omode,&ncp))) goto done; | 
| 2172 |  |  | 
| 2173 |  |     /* Add to list of known open files. This assigns an ext_ncid. */ | 
| 2174 | 291 |     add_to_NCList(ncp); | 
| 2175 |  |  | 
| 2176 |  |     /* Assume open will fill in remaining ncp fields */ | 
| 2177 | 291 |     stat = dispatcher->open(ncp->path, omode, basepe, chunksizehintp, | 
| 2178 | 291 |                             parameters, dispatcher, ncp->ext_ncid); | 
| 2179 | 291 |     if(stat == NC_NOERR) { | 
| 2180 | 11 |         if(ncidp) *ncidp = ncp->ext_ncid; | 
| 2181 | 280 |     } else { | 
| 2182 | 280 |         del_from_NCList(ncp); | 
| 2183 | 280 |         free_NC(ncp); | 
| 2184 | 280 |     } | 
| 2185 |  |  | 
| 2186 | 339 | done: | 
| 2187 | 339 |     nullfree(path); | 
| 2188 | 339 |     nullfree(newpath); | 
| 2189 | 339 |     return stat; | 
| 2190 | 291 | } | 
| 2191 |  |  | 
| 2192 |  | /*Provide an internal function for generating pseudo file descriptors | 
| 2193 |  |   for systems that are not file based (e.g. dap, memio). | 
| 2194 |  | */ | 
| 2195 |  |  | 
| 2196 |  | /** @internal Static counter for pseudo file descriptors (incremented) */ | 
| 2197 |  | static int pseudofd = 0; | 
| 2198 |  |  | 
| 2199 |  | /** | 
| 2200 |  |  * @internal Create a pseudo file descriptor that does not | 
| 2201 |  |  * overlap real file descriptors | 
| 2202 |  |  * | 
| 2203 |  |  * @return pseudo file number | 
| 2204 |  |  * @author Dennis Heimbigner | 
| 2205 |  |  */ | 
| 2206 |  | int | 
| 2207 |  | nc__pseudofd(void) | 
| 2208 | 291 | { | 
| 2209 | 291 |     if(pseudofd == 0)  { | 
| 2210 | 1 | #ifdef HAVE_GETRLIMIT | 
| 2211 | 1 |         int maxfd = 32767; /* default */ | 
| 2212 | 1 |         struct rlimit rl; | 
| 2213 | 1 |         if(getrlimit(RLIMIT_NOFILE,&rl) == 0) { | 
| 2214 | 1 |             if(rl.rlim_max != RLIM_INFINITY) | 
| 2215 | 1 |                 maxfd = (int)rl.rlim_max; | 
| 2216 | 1 |             if(rl.rlim_cur != RLIM_INFINITY) | 
| 2217 | 1 |                 maxfd = (int)rl.rlim_cur; | 
| 2218 | 1 |         } | 
| 2219 | 1 |         pseudofd = maxfd+1; | 
| 2220 | 1 | #endif | 
| 2221 | 1 |     } | 
| 2222 | 291 |     return pseudofd++; | 
| 2223 | 291 | } | 
| 2224 |  | /** \} */ |