1 /** \file
2 The V2 API Functions.
3 
4 Copyright 1996, University Corporation for Atmospheric Research
5 See \ref copyright file for copying and redistribution conditions.
6  */
7 
8 #ifndef NO_NETCDF_2
9 
10 #include "config.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include "netcdf.h"
15 #include <math.h>
16 
17 /** \defgroup v2_api The Version 2 API
18 
19 NetCDF's modern history began with the introduction of the V2 netCDF
20 API by Glenn Davis and Russ Rew in 1991. (The V1 API is lost to mists
21 of time.)
22 
23 The V2 API is still fully supported, but should not be used for new
24 development.
25 
26 All of the V2 functions have been reimplemented in terms of the V3 API
27 code; see the documentation for the related V3 functions to get more
28 documentation.
29 
30 The V2 API is tested in test directory nctest.
31 */
32 
33 /** The subroutines in error.c emit no messages unless NC_VERBOSE bit
34  * is on.  They call exit() when NC_FATAL bit is on. */
35 int ncopts = (NC_FATAL | NC_VERBOSE) ;
36 
37 int ncerr = NC_NOERR ; /**< V2 API error code. */
38 
39 #if SIZEOF_LONG == SIZEOF_SIZE_T
40 /*
41  * We don't have to copy the arguments to switch from 'long'
42  * to 'size_t' or 'ptrdiff_t'. Use dummy macros.
43  */
44 
45 # define NDIMS_DECL  /**< NDIMS declaration */
46 
47 /** @internal Declaration. */
48 # define A_DECL(name, type, ndims, rhs) \
49 	const type *const name = ((const type *)(rhs))
50 
51 # define A_FREE(name)  /**< Free a variable. */
52 
53 # define A_INIT(lhs, type, ndims, rhs)  /**< Init a variable */
54 
55 #else
56 /*
57  * We do have to copy the arguments to switch from 'long'
58  * to 'size_t' or 'ptrdiff_t'. In my tests on an SGI,
59  * any additional cost was lost in measurement variation.
60  *
61  * This stanza is true on Windows with MinGW-64
62  */
63 
64 # include "onstack.h"
65 
66 static int
nvdims(int ncid,int varid)67 nvdims(int ncid, int varid)
68 {
69    int ndims=-1, status;
70 
71    if ((status = nc_inq_varndims(ncid, varid, &ndims)))
72    {
73       nc_advise("ncvdims", status, "ncid %d", ncid);
74       return -1;
75    }
76    return ndims;
77 }
78 
79 /* Used to avoid errors on 64-bit windows related to
80    c89 macros and flow control/conditionals. */
nvmalloc(off_t size)81 static void* nvmalloc(off_t size) {
82   if(size < 0)
83     return NULL;
84 
85   return malloc(size);
86 
87 }
88 
89 #define NDIMS_DECL const int ndims = nvdims(ncid, varid); \
90 
91 
92 # define A_DECL(name, type, ndims, rhs)		\
93   type *const name = (type*) nvmalloc((ndims) * sizeof(type))
94 
95 
96 #if 0
97   ALLOC_ONSTACK(name, type, ndims)
98 #endif
99 
100 # define A_FREE(name) \
101 	FREE_ONSTACK(name)
102 
103 # define A_INIT(lhs, type, ndims, rhs) \
104 	{ \
105 	  if((off_t)ndims >= 0) {     \
106 		const long *lp = rhs; \
107 		type *tp = lhs; \
108 		type *const end = lhs + ndims; \
109 		while(tp < end) \
110 		{ \
111 			*tp++ = (type) *lp++; \
112 		} \
113 		} \
114 	} \
115 	\
116     if ((off_t)ndims < 0) {nc_advise("nvdims",NC_EMAXDIMS,"ndims %d",ndims); return -1;}
117 
118 
119 #endif
120 
121 typedef signed char schar;  /**< Signed character type. */
122 
123 /**
124  * Computes number of record variables in an open netCDF file, and an array of
125  * the record variable ids, if the array parameter is non-null.
126  *
127  * @param ncid File ID.
128  * @param nrecvarsp Pointer that gets number of record variables.
129  * @param recvarids Pointer that gets array of record variable IDs.
130  *
131  * @return ::NC_NOERR No error.
132  * @return -1 on error.
133  * @author Russ Rew
134  */
135 static int
numrecvars(int ncid,int * nrecvarsp,int * recvarids)136 numrecvars(int ncid, int* nrecvarsp, int *recvarids)
137 {
138     int status = NC_NOERR;
139     int nvars = 0;
140     int ndims = 0;
141     int nrecvars = 0;
142     int varid;
143     int recdimid;
144     int dimids[MAX_NC_DIMS];
145 
146     status = nc_inq_nvars(ncid, &nvars);
147     if(status != NC_NOERR)
148 	return status;
149 
150     status = nc_inq_unlimdim(ncid, &recdimid);
151     if(status != NC_NOERR)
152 	return status;
153 
154     if (recdimid == -1) {
155 	*nrecvarsp = 0;
156 	return NC_NOERR;
157     }
158     nrecvars = 0;
159     for (varid = 0; varid < nvars; varid++) {
160 	status = nc_inq_varndims(ncid, varid, &ndims);
161 	if(status != NC_NOERR)
162 	    return status;
163 	status = nc_inq_vardimid(ncid, varid, dimids);
164 	if(status != NC_NOERR)
165 	    return status;
166 	if (ndims > 0 && dimids[0] == recdimid) {
167 	    if (recvarids != NULL)
168 	      recvarids[nrecvars] = varid;
169 	    nrecvars++;
170 	}
171     }
172     *nrecvarsp = nrecvars;
173     return NC_NOERR;
174 }
175 
176 
177 /**
178  * Computes record size (in bytes) of the record variable with a specified
179  * variable id.  Returns size as 0 if not a record variable.
180  *
181  * @param ncid File ID.
182  * @param varid Variable ID.
183  * @param recsizep Pointer that gets record size.
184  *
185  * @return size, or 0 if not a record variable
186  */
187 static int
ncrecsize(int ncid,int varid,size_t * recsizep)188 ncrecsize(int ncid, int varid, size_t *recsizep)
189 {
190     int status = NC_NOERR;
191     int recdimid;
192     nc_type type;
193     int ndims;
194     int dimids[MAX_NC_DIMS];
195     int id;
196     int size;
197 
198     *recsizep = 0;
199     status = nc_inq_unlimdim(ncid, &recdimid);
200     if(status != NC_NOERR)
201 	return status;
202     status = nc_inq_vartype(ncid, varid, &type);
203     if(status != NC_NOERR)
204 	return status;
205     status = nc_inq_varndims(ncid, varid, &ndims);
206     if(status != NC_NOERR)
207 	return status;
208     status = nc_inq_vardimid(ncid, varid, dimids);
209     if(status != NC_NOERR)
210 	return status;
211     if (ndims == 0 || dimids[0] != recdimid) {
212 	return NC_NOERR;
213     }
214     size = nctypelen(type);
215     for (id = 1; id < ndims; id++) {
216 	size_t len;
217 	status = nc_inq_dimlen(ncid, dimids[id], &len);
218 	if(status != NC_NOERR)
219 		return status;
220 	size *= (int)len;
221     }
222     *recsizep = (size_t)size;
223     return NC_NOERR;
224 }
225 
226 
227 /**
228  * Retrieves the dimension sizes of a variable with a specified variable id in
229  * an open netCDF file.
230  *
231  * @param ncid File ID.
232  * @param varid Variable ID.
233  * @param sizes Pointer that gets sizes.
234  *
235  * @return ::NC_NOERR No error.
236  * @return -1 on error.
237  * @author Russ Rew
238  */
239 static int
dimsizes(int ncid,int varid,size_t * sizes)240 dimsizes(int ncid, int varid, size_t *sizes)
241 {
242     int status = NC_NOERR;
243     int ndims;
244     int id;
245     int dimids[MAX_NC_DIMS];
246 
247     status = nc_inq_varndims(ncid, varid, &ndims);
248     if(status != NC_NOERR)
249 	return status;
250     status = nc_inq_vardimid(ncid, varid, dimids);
251     if(status != NC_NOERR)
252 	return status;
253     if (ndims == 0 || sizes == NULL)
254       return NC_NOERR;
255     for (id = 0; id < ndims; id++) {
256 	size_t len;
257 	status = nc_inq_dimlen(ncid, dimids[id], &len);
258 	if(status != NC_NOERR)
259 		return status;
260 	sizes[id] = len;
261     }
262     return NC_NOERR;
263 }
264 
265 /** \ingroup v2_api
266 
267 Retrieves the number of record variables, the record variable ids, and the
268 record size of each record variable.  If any pointer to info to be returned
269 is null, the associated information is not returned.  Returns -1 on error.
270 
271 This is part of the legacy V2 API of netCDF. New code should be
272 written with the V3 API. See V3 functions nc_inq_nvars(),
273 nc_inq_unlimdim(), nc_inq_dim().
274 
275 \param ncid file ID
276 \param nrecvarsp pointer that will get the number of record variables
277 in the file.
278 \param recvarids pointer to array that will get the variable IDs of
279 all variables that use the record dimension.
280 \param recsizes pointer to array that will dimension size of the
281 record dimension for each variable.
282 
283 \returns ::NC_NOERR No error.
284 \returns ::NC_EBADID Bad ncid.
285 \returns ::NC_ENOTVAR Invalid variable ID.
286 \returns ::NC_EINVAL Invalid input
287 */
288 int
nc_inq_rec(int ncid,size_t * nrecvarsp,int * recvarids,size_t * recsizes)289 nc_inq_rec(
290 	int ncid,
291 	size_t *nrecvarsp,
292 	int *recvarids,
293 	size_t *recsizes)
294 {
295     int status = NC_NOERR;
296     int nvars = 0;
297     int recdimid;
298     int varid;
299     int rvarids[MAX_NC_VARS];
300     int nrvars = 0;
301 
302     status = nc_inq_nvars(ncid, &nvars);
303     if(status != NC_NOERR)
304 	return status;
305 
306     status = nc_inq_unlimdim(ncid, &recdimid);
307     if(status != NC_NOERR)
308 	return status;
309 
310     if (recdimid == -1)
311 	return NC_NOERR;
312 
313     status = numrecvars(ncid, &nrvars, rvarids);
314     if(status != NC_NOERR)
315 	return status;
316 
317     if (nrecvarsp != NULL)
318 	*nrecvarsp = (size_t)nrvars;
319 
320     if (recvarids != NULL)
321 	for (varid = 0; varid < nrvars; varid++)
322 	    recvarids[varid] = rvarids[varid];
323 
324     if (recsizes != NULL)
325 	for (varid = 0; varid < nrvars; varid++) {
326 	    size_t rsize;
327 	    status = ncrecsize(ncid, rvarids[varid], &rsize);
328 	    if (status != NC_NOERR)
329 		return status;
330 	    recsizes[varid] = rsize;
331 	}
332     return NC_NOERR;
333 }
334 
335 /** \ingroup v2_api
336 
337 Write one record's worth of data, except don't write to variables for which
338 the address of the data to be written is NULL.  Return -1 on error.  This is
339 the same as the ncrecput() in the library, except that can handle errors
340 better.
341 
342 This is part of the legacy V2 API of netCDF. New code should be
343 written with the V3 API. See V3 function nc_put_vara().
344 
345 \param ncid file ID
346 \param recnum the record number to write.
347 \param datap pointer to one record's worth of data for all variables.
348 
349 \returns ::NC_NOERR No error.
350 \returns ::NC_EBADID Bad ncid.
351 \returns ::NC_ENOTVAR Invalid variable ID.
352 \returns ::NC_EINVAL Invalid input
353 */
354 int
nc_put_rec(int ncid,size_t recnum,void * const * datap)355 nc_put_rec(
356 	int ncid,
357 	size_t recnum,
358 	void* const* datap)
359 {
360     int status = NC_NOERR;
361     int varid;
362     int rvarids[MAX_NC_VARS];
363     int nrvars;
364     size_t start[MAX_NC_DIMS];
365     size_t edges[MAX_NC_DIMS];
366 
367     status = numrecvars(ncid, &nrvars, rvarids);
368     if(status != NC_NOERR)
369 	return status;
370 
371     if (nrvars == 0)
372       return NC_NOERR;
373 
374     start[0] = recnum;
375     for (varid = 1; varid < nrvars; varid++)
376 	start[varid] = 0;
377 
378     for (varid = 0; varid < nrvars; varid++) {
379 	if (datap[varid] != NULL) {
380 	    status = dimsizes(ncid, rvarids[varid], edges);
381 	    if(status != NC_NOERR)
382 		return status;
383 
384 	    edges[0] = 1;		/* only 1 record's worth */
385 	    status = nc_put_vara(ncid, rvarids[varid], start, edges, datap[varid]);
386 	    if(status != NC_NOERR)
387 		return status;
388 	}
389     }
390     return 0;
391 }
392 
393 
394 /** \ingroup v2_api
395 
396 Read one record's worth of data, except don't read from variables for which
397 the address of the data to be read is null.  Return -1 on error.  This is
398 the same as the ncrecget() in the library, except that can handle errors
399 better.
400 
401 This is part of the legacy V2 API of netCDF. New code should be
402 written with the V3 API. See V3 function nc_get_vara().
403 
404 \param ncid file ID
405 \param recnum the record number to read.
406 \param datap pointer memory to hold one record's worth of data for all
407 variables.
408 
409 \returns ::NC_NOERR No error.
410 \returns ::NC_EBADID Bad ncid.
411 \returns ::NC_ENOTVAR Invalid variable ID.
412 \returns ::NC_EINVAL Invalid input
413 
414 */
415 int
nc_get_rec(int ncid,size_t recnum,void ** datap)416 nc_get_rec(
417 	int ncid,
418 	size_t recnum,
419 	void **datap)
420 {
421     int status = NC_NOERR;
422     int varid;
423     int rvarids[MAX_NC_VARS];
424     int nrvars;
425     size_t start[MAX_NC_DIMS];
426     size_t edges[MAX_NC_DIMS];
427 
428     status = numrecvars(ncid, &nrvars, rvarids);
429     if(status != NC_NOERR)
430 	return status;
431 
432     if (nrvars == 0)
433       return NC_NOERR;
434 
435     start[0] = recnum;
436     for (varid = 1; varid < nrvars; varid++)
437 	start[varid] = 0;
438 
439     for (varid = 0; varid < nrvars; varid++) {
440 	if (datap[varid] != NULL) {
441 	    status = dimsizes(ncid, rvarids[varid], edges);
442 	    if(status != NC_NOERR)
443 		return status;
444 	    edges[0] = 1;		/* only 1 record's worth */
445 	    status = nc_get_vara(ncid, rvarids[varid], start, edges, datap[varid]);
446 	    if(status != NC_NOERR)
447 		return status;
448 	}
449     }
450     return 0;
451 }
452 
453 /** \ingroup v2_api
454 
455 Show an error message and exit (based on ncopts).
456 
457 This is part of the legacy V2 API of netCDF. New code should be
458 written with the V3 API. See V3 function nc_strerror()
459 
460 \param routine_name
461 \param err error code
462 \param fmt pointer to a char array containing string format
463 
464 */
465 void
nc_advise(const char * routine_name,int err,const char * fmt,...)466 nc_advise(const char *routine_name, int err, const char *fmt,...)
467 {
468 	va_list args;
469 
470 	if(NC_ISSYSERR(err))
471 		ncerr = NC_SYSERR;
472 	else
473 		ncerr = err;
474 
475 	if( ncopts & NC_VERBOSE )
476 	{
477 		(void) fprintf(stderr,"%s: ", routine_name);
478 		va_start(args ,fmt);
479 		(void) vfprintf(stderr,fmt,args);
480 		va_end(args);
481 		if(err != NC_NOERR)
482 		{
483 			(void) fprintf(stderr,": %s",
484 				nc_strerror(err));
485 		}
486 		(void) fputc('\n',stderr);
487 		(void) fflush(stderr);	/* to ensure log files are current */
488 	}
489 
490 	if( (ncopts & NC_FATAL) && err != NC_NOERR )
491 	{
492 		exit(ncopts);
493 	}
494 }
495 
496 /* End error handling */
497 
498 /** \ingroup v2_api
499 
500 Create a netCDF file.
501 
502 This is part of the legacy V2 API of netCDF. New code should be
503 written with the V3 API. See V3 function nc_create().
504 
505 \param path path and filename of the file to be created.
506 \param cmode see nc_create() for full discussion of the create mode.
507 
508 \returns the ncid of the created file.
509 */
510 int
nccreate(const char * path,int cmode)511 nccreate(const char* path, int cmode)
512 {
513 	int ncid;
514 	const int status = nc_create(path, cmode, &ncid);
515 	if(status != NC_NOERR)
516 	{
517 		nc_advise("nccreate", status, "filename \"%s\"", path);
518 		return -1;
519 	}
520 	return ncid;
521 }
522 
523 /** \ingroup v2_api
524 
525 Open a netCDF file.
526 
527 This is part of the legacy V2 API of netCDF. New code should be
528 written with the V3 API. See V3 function nc_open().
529 
530 \param path path and filename of the file to be created.
531 \param mode see nc_open() for full discussion of the open mode.
532 
533 \returns the ncid of the created file.
534 */
535 int
ncopen(const char * path,int mode)536 ncopen(const char *path, int mode)
537 {
538 	int ncid;
539 	const int status = nc_open(path, mode, &ncid);
540 	if(status != NC_NOERR)
541 	{
542 		nc_advise("ncopen", status, "filename \"%s\"", path);
543 		return -1;
544 	}
545 	return ncid;
546 }
547 
548 /** \ingroup v2_api
549 
550 Put file in define mode.
551 
552 This is part of the legacy V2 API of netCDF. New code should be
553 written with the V3 API. See V3 function nc_redef().
554 
555 \param ncid file ID
556 
557 \returns 0 for success, -1 for failure.
558 */
559 int
ncredef(int ncid)560 ncredef(int ncid)
561 {
562 	const int status =  nc_redef(ncid);
563 	if(status != NC_NOERR)
564 	{
565 		nc_advise("ncredef", status, "ncid %d", ncid);
566 		return -1;
567 	}
568 	return 0;
569 }
570 
571 /** \ingroup v2_api
572 
573 End define mode for file.
574 
575 This is part of the legacy V2 API of netCDF. New code should be
576 written with the V3 API. See V3 function nc_enddef().
577 
578 \param ncid file ID
579 
580 \returns 0 for success, -1 for failure.
581 */
582 int
ncendef(int ncid)583 ncendef(int ncid)
584 {
585 	const int status = nc_enddef(ncid);
586 	if(status != NC_NOERR)
587 	{
588 		nc_advise("ncendef", status, "ncid %d", ncid);
589 		return -1;
590 	}
591 	return 0;
592 }
593 
594 /** \ingroup v2_api
595 
596 Close a file.
597 
598 This is part of the legacy V2 API of netCDF. New code should be
599 written with the V3 API. See V3 function nc_close().
600 
601 \param ncid file ID
602 
603 \returns 0 for success, -1 for failure.
604 */
605 int
ncclose(int ncid)606 ncclose(int ncid)
607 {
608 	const int status = nc_close(ncid);
609 	if(status != NC_NOERR)
610 	{
611 		nc_advise("ncclose", status, "ncid %d", ncid);
612 		return -1;
613 
614 	}
615 	return 0;
616 }
617 
618 /** \ingroup v2_api
619 
620 Learn about a file.
621 
622 This is part of the legacy V2 API of netCDF. New code should be
623 written with the V3 API. See V3 function nc_inq().
624 
625 \param ncid file ID
626 \param ndims pointer that will get number of dimensions.
627 \param nvars pointer that will get number of variables.
628 \param natts pointer that will get number of global attributes.
629 \param recdim pointer that will get dimension ID of record dimension,
630 or -1 if there is no record dimension.
631 
632 \returns 0 for success, -1 for failure.
633 */
634 int
ncinquire(int ncid,int * ndims,int * nvars,int * natts,int * recdim)635 ncinquire(
636     int		ncid,
637     int*	ndims,
638     int*	nvars,
639     int*	natts,
640     int*	recdim
641 )
642 {
643 	int nd, nv, na;
644 	const int status = nc_inq(ncid, &nd, &nv, &na, recdim);
645 
646 	if(status != NC_NOERR)
647 	{
648 		nc_advise("ncinquire", status, "ncid %d", ncid);
649 		return -1;
650 	}
651 	/* else */
652 
653 	if(ndims != NULL)
654 		*ndims = (int) nd;
655 
656 	if(nvars != NULL)
657 		*nvars = (int) nv;
658 
659 	if(natts != NULL)
660 		*natts = (int) na;
661 
662 	return ncid;
663 }
664 
665 /** \ingroup v2_api
666 
667 Sync a file.
668 
669 This is part of the legacy V2 API of netCDF. New code should be
670 written with the V3 API. See V3 function nc_sync().
671 
672 \param ncid file ID
673 
674 \returns 0 for success, -1 for failure.
675 */
676 int
ncsync(int ncid)677 ncsync(int ncid)
678 {
679 	const int status = nc_sync(ncid);
680 	if(status != NC_NOERR)
681 	{
682 		nc_advise("ncsync", status, "ncid %d", ncid);
683 		return -1;
684 
685 	}
686 	return 0;
687 }
688 
689 /** \ingroup v2_api
690 
691 Abort defining a file.
692 
693 This is part of the legacy V2 API of netCDF. New code should be
694 written with the V3 API. See V3 function nc_abort().
695 
696 \param ncid file ID
697 \returns 0 for success, -1 for failure.
698 */
699 int
ncabort(int ncid)700 ncabort(int ncid)
701 {
702 	const int status = nc_abort(ncid);
703 	if(status != NC_NOERR)
704 	{
705 		nc_advise("ncabort", status, "ncid %d", ncid);
706 		return -1;
707 	}
708 	return 0;
709 }
710 
711 /** \ingroup v2_api
712 
713 Define a dimension.
714 
715 This is part of the legacy V2 API of netCDF. New code should be
716 written with the V3 API. See V3 function nc_def_dim().
717 
718 \param ncid file ID
719 \param name name of dimension.
720 \param length length of the dimension, NC_UNLIMITED for a record
721 dimension.
722 
723 \returns dimid or -1 for failure.
724 */
725 int
ncdimdef(int ncid,const char * name,long length)726 ncdimdef(
727     int		ncid,
728     const char*	name,
729     long	length
730 )
731 {
732 	int dimid;
733 	int status = NC_NOERR;
734 	if(length < 0) {
735 	    status = NC_EDIMSIZE;
736 	    nc_advise("ncdimdef", status, "ncid %d", ncid);
737 	    return -1;
738 	}
739 	status =  nc_def_dim(ncid, name, (size_t)length, &dimid);
740 	if(status != NC_NOERR)
741 	{
742 		nc_advise("ncdimdef", status, "ncid %d", ncid);
743 		return -1;
744 	}
745 	return dimid;
746 }
747 
748 /** \ingroup v2_api
749 
750 Find dimension ID from name.
751 
752 This is part of the legacy V2 API of netCDF. New code should be
753 written with the V3 API. See V3 function nc_inq_dimid().
754 
755 \param ncid file ID
756 \param name name of dimension.
757 
758 \returns dimid or -1 for failure.
759 */
760 int
ncdimid(int ncid,const char * name)761 ncdimid(int ncid, const char*	name)
762 {
763 	int dimid;
764 	const int status =  nc_inq_dimid(ncid, name, &dimid);
765 	if(status != NC_NOERR)
766 	{
767 		nc_advise("ncdimid", status, "ncid %d", ncid);
768 		return -1;
769 	}
770 	return dimid;
771 }
772 
773 /** \ingroup v2_api
774 
775 Learn about a dimension.
776 
777 This is part of the legacy V2 API of netCDF. New code should be
778 written with the V3 API. See V3 function nc_inq_dim().
779 
780 \param ncid file ID
781 \param dimid the dimension ID to learn about
782 \param name pointer that will get name of dimension.
783 \param length pointer that will get length of dimension.
784 
785 \returns dimid or -1 for failure.
786 */
787 int
ncdiminq(int ncid,int dimid,char * name,long * length)788 ncdiminq(
789     int		ncid,
790     int		dimid,
791     char*	name,
792     long*	length
793 )
794 {
795 	size_t ll;
796 	const int status = nc_inq_dim(ncid, dimid, name, &ll);
797 
798 	if(status != NC_NOERR)
799 	{
800 		nc_advise("ncdiminq", status, "ncid %d", ncid);
801 		return -1;
802 	}
803 	/* else */
804 
805 	if(length != NULL)
806 		*length = (int) ll;
807 
808 	return dimid;
809 }
810 
811 /** \ingroup v2_api
812 
813 Rename a dimension.
814 
815 This is part of the legacy V2 API of netCDF. New code should be
816 written with the V3 API. See V3 function nc_rename_dim().
817 
818 \param ncid file ID
819 \param dimid the dimension ID.
820 \param name the new name.
821 
822 \returns dimid or -1 for failure.
823 */
824 int
ncdimrename(int ncid,int dimid,const char * name)825 ncdimrename(
826     int		ncid,
827     int		dimid,
828     const char*	name
829 )
830 {
831 	const int status = nc_rename_dim(ncid, dimid, name);
832 	if(status != NC_NOERR)
833 	{
834 		nc_advise("ncdimrename", status, "ncid %d", ncid);
835 		return -1;
836 	}
837 	return dimid;
838 }
839 
840 /** \ingroup v2_api
841 
842 Define a variable.
843 
844 This is part of the legacy V2 API of netCDF. New code should be
845 written with the V3 API. See V3 function nc_def_var().
846 
847 \param ncid file ID
848 \param name the name of the variable.
849 \param datatype the data type of the variable.
850 \param ndims the number of dimensions.
851 \param dim array of dimension IDs.
852 
853 \returns varid or -1 for failure.
854 */
855 int
ncvardef(int ncid,const char * name,nc_type datatype,int ndims,const int * dim)856 ncvardef(
857     int		ncid,
858     const char*	name,
859     nc_type	datatype,
860     int		ndims,
861     const int*	dim
862 )
863 {
864 	int varid = -1;
865 	const int status = nc_def_var(ncid, name, datatype, ndims, dim, &varid);
866 	if(status != NC_NOERR)
867 	{
868 		nc_advise("ncvardef", status, "ncid %d", ncid);
869 		return -1;
870 	}
871 	return varid;
872 }
873 
874 /** \ingroup v2_api
875 
876 Learn a variable ID from the name.
877 
878 This is part of the legacy V2 API of netCDF. New code should be
879 written with the V3 API. See V3 function nc_inq_varid().
880 
881 \param ncid file ID
882 \param name the name of the variable.
883 
884 \returns varid or -1 for failure.
885 */
886 int
ncvarid(int ncid,const char * name)887 ncvarid(
888     int		ncid,
889     const char*	name
890 )
891 {
892 	int varid = -1;
893 	const int status = nc_inq_varid(ncid, name, &varid);
894 	if(status != NC_NOERR)
895 	{
896 		nc_advise("ncvarid", status, "ncid %d", ncid);
897 		return -1;
898 	}
899 	return varid;
900 }
901 
902 /** \ingroup v2_api
903 
904 Learn about a variable.
905 
906 This is part of the legacy V2 API of netCDF. New code should be
907 written with the V3 API. See V3 function nc_inq_var().
908 
909 \param ncid file ID
910 \param varid the variable ID.
911 \param name pointer to array of char that will get name of variable.
912 \param datatype pointer that will get variable data type.
913 \param ndims pointer that will get number of dimensions.
914 \param dim pointer to array that will get dimension IDs.
915 \param natts pointer that will get number of variable attributes.
916 
917 \returns varid or -1 for failure.
918 */
919 int
ncvarinq(int ncid,int varid,char * name,nc_type * datatype,int * ndims,int * dim,int * natts)920 ncvarinq(
921     int		ncid,
922     int		varid,
923     char*	name,
924     nc_type*	datatype,
925     int*	ndims,
926     int*	dim,
927     int*	natts
928 )
929 {
930 	int nd, na;
931 	const int status = nc_inq_var(ncid, varid, name, datatype,
932 		 &nd, dim, &na);
933 
934 	if(status != NC_NOERR)
935 	{
936 		nc_advise("ncvarinq", status, "ncid %d", ncid);
937 		return -1;
938 	}
939 	/* else */
940 
941 	if(ndims != NULL)
942 		*ndims = (int) nd;
943 
944 	if(natts != NULL)
945 		*natts = (int) na;
946 
947 	return varid;
948 }
949 
950 /** \ingroup v2_api
951 
952 Write 1 data value.
953 
954 This is part of the legacy V2 API of netCDF. New code should be
955 written with the V3 API. See V3 function nc_put_var1().
956 
957 \param ncid file ID
958 \param varid the variable ID.
959 \param index pointer to array of index values.
960 \param value pointer to data.
961 
962 \returns 0 for success or -1 for failure.
963 */
964 int
ncvarput1(int ncid,int varid,const long * index,const void * value)965 ncvarput1(
966     int		ncid,
967     int		varid,
968     const long*	index,
969     const void*	value
970 )
971 {
972 	NDIMS_DECL
973 	A_DECL(coordp, size_t, (size_t)ndims, index);
974 	A_INIT(coordp, size_t, (size_t)ndims, index);
975 	{
976 	const int status = nc_put_var1(ncid, varid, coordp, value);
977 	A_FREE(coordp);
978 	if(status != NC_NOERR)
979 	{
980 		nc_advise("ncvarput1", status, "ncid %d", ncid);
981 		return -1;
982 	}
983 	}
984 	return 0;
985 }
986 
987 /** \ingroup v2_api
988 
989 Read 1 data value.
990 
991 This is part of the legacy V2 API of netCDF. New code should be
992 written with the V3 API. See V3 function nc_get_var1().
993 
994 \param ncid file ID
995 \param varid the variable ID.
996 \param index pointer to array of index values.
997 \param value pointer that will get data.
998 
999 \returns 0 for success or -1 for failure.
1000 */
1001 int
ncvarget1(int ncid,int varid,const long * index,void * value)1002 ncvarget1(
1003     int		ncid,
1004     int		varid,
1005     const long*	index,
1006     void*	value
1007 )
1008 {
1009 	NDIMS_DECL
1010 	A_DECL(coordp, size_t, ndims, index);
1011 	A_INIT(coordp, size_t, ndims, index);
1012 	{
1013 	const int status = nc_get_var1(ncid, varid, coordp, value);
1014 	A_FREE(coordp);
1015 	if(status != NC_NOERR)
1016 	{
1017 		nc_advise("ncdimid", status, "ncid %d", ncid);
1018 		return -1;
1019 	}
1020 	}
1021 	return 0;
1022 }
1023 
1024 /** \ingroup v2_api
1025 
1026 Write some data.
1027 
1028 This is part of the legacy V2 API of netCDF. New code should be
1029 written with the V3 API. See V3 function nc_put_vara().
1030 
1031 \param ncid file ID
1032 \param varid the variable ID.
1033 \param start pointer to array of start values.
1034 \param count pointer to array of count values.
1035 \param value pointer to data.
1036 
1037 \returns 0 for success or -1 for failure.
1038 */
1039 int
ncvarput(int ncid,int varid,const long * start,const long * count,const void * value)1040 ncvarput(
1041     int		ncid,
1042     int		varid,
1043     const long*	start,
1044     const long*	count,
1045     const void*	value
1046 )
1047 {
1048 	NDIMS_DECL
1049 	A_DECL(stp, size_t, ndims, start);
1050 	A_DECL(cntp, size_t, ndims, count);
1051 	A_INIT(stp, size_t, ndims, start);
1052 	A_INIT(cntp, size_t, ndims, count);
1053 	{
1054 	const int status = nc_put_vara(ncid, varid, stp, cntp, value);
1055 	A_FREE(cntp);
1056 	A_FREE(stp);
1057 	if(status != NC_NOERR)
1058 	{
1059 		nc_advise("ncvarput", status, "ncid %d", ncid);
1060 		return -1;
1061 	}
1062 	}
1063 	return 0;
1064 }
1065 
1066 /** \ingroup v2_api
1067 
1068 Read some data.
1069 
1070 This is part of the legacy V2 API of netCDF. New code should be
1071 written with the V3 API. See V3 function nc_get_vara().
1072 
1073 \param ncid file ID
1074 \param varid the variable ID.
1075 \param start pointer to array of start values.
1076 \param count pointer to array of count values.
1077 \param value pointer to data.
1078 
1079 \returns 0 for success or -1 for failure.
1080 */
1081 int
ncvarget(int ncid,int varid,const long * start,const long * count,void * value)1082 ncvarget(
1083     int		ncid,
1084     int		varid,
1085     const long*	start,
1086     const long*	count,
1087     void*	value
1088 )
1089 {
1090 	NDIMS_DECL
1091 	A_DECL(stp, size_t, ndims, start);
1092 	A_DECL(cntp, size_t, ndims, count);
1093 	A_INIT(stp, size_t, ndims, start);
1094 	A_INIT(cntp, size_t, ndims, count);
1095 	{
1096 	const int status = nc_get_vara(ncid, varid, stp, cntp, value);
1097 	A_FREE(cntp);
1098 	A_FREE(stp);
1099 	if(status != NC_NOERR)
1100 	{
1101 		nc_advise("ncvarget", status, "ncid %d; varid %d", ncid, varid);
1102 		return -1;
1103 	}
1104 	}
1105 	return 0;
1106 }
1107 
1108 /** \ingroup v2_api
1109 
1110 Write strided data.
1111 
1112 This is part of the legacy V2 API of netCDF. New code should be
1113 written with the V3 API. See V3 function nc_put_vars().
1114 
1115 \param ncid file ID
1116 \param varid the variable ID.
1117 \param start pointer to array of start values.
1118 \param count pointer to array of count values.
1119 \param stride pointer to array of stride values.
1120 \param value pointer to data.
1121 
1122 \returns 0 for success or -1 for failure.
1123 */
1124 int
ncvarputs(int ncid,int varid,const long * start,const long * count,const long * stride,const void * value)1125 ncvarputs(
1126     int		ncid,
1127     int		varid,
1128     const long*	start,
1129     const long*	count,
1130     const long*	stride,
1131     const void*	value
1132 )
1133 {
1134 	if(stride == NULL)
1135 		return ncvarput(ncid, varid, start, count, value);
1136 	/* else */
1137 	{
1138 
1139 	NDIMS_DECL
1140 	A_DECL(stp, size_t, ndims, start);
1141 	A_DECL(cntp, size_t, ndims, count);
1142 	A_DECL(strdp, ptrdiff_t, ndims, stride);
1143 	A_INIT(stp, size_t, ndims, start);
1144 	A_INIT(cntp, size_t, ndims, count);
1145 	A_INIT(strdp, ptrdiff_t, ndims, stride);
1146 	{
1147 	const int status = nc_put_vars(ncid, varid, stp, cntp, strdp, value);
1148 	A_FREE(strdp);
1149 	A_FREE(cntp);
1150 	A_FREE(stp);
1151 	if(status != NC_NOERR)
1152 	{
1153 		nc_advise("ncvarputs", status, "ncid %d", ncid);
1154 		return -1;
1155 	}
1156 	}
1157 	return 0;
1158 	}
1159 }
1160 
1161 /** \ingroup v2_api
1162 
1163 Read strided data.
1164 
1165 This is part of the legacy V2 API of netCDF. New code should be
1166 written with the V3 API. See V3 function nc_get_vars().
1167 
1168 \param ncid file ID
1169 \param varid the variable ID.
1170 \param start pointer to array of start values.
1171 \param count pointer to array of count values.
1172 \param stride pointer to array of stride values.
1173 \param value pointer to data.
1174 
1175 \returns 0 for success or -1 for failure.
1176 */
1177 int
ncvargets(int ncid,int varid,const long * start,const long * count,const long * stride,void * value)1178 ncvargets(
1179     int		ncid,
1180     int		varid,
1181     const long*	start,
1182     const long*	count,
1183     const long*	stride,
1184     void*	value
1185 )
1186 {
1187 	if(stride == NULL)
1188 		return ncvarget(ncid, varid, start, count, value);
1189 	/* else */
1190 	{
1191 	NDIMS_DECL
1192 	A_DECL(stp, size_t, ndims, start);
1193 	A_DECL(cntp, size_t, ndims, count);
1194 	A_DECL(strdp, ptrdiff_t, ndims, stride);
1195 	A_INIT(stp, size_t, ndims, start);
1196 	A_INIT(cntp, size_t, ndims, count);
1197 	A_INIT(strdp, ptrdiff_t, ndims, stride);
1198 	{
1199 	const int status = nc_get_vars(ncid, varid, stp, cntp, strdp, value);
1200 	A_FREE(strdp);
1201 	A_FREE(cntp);
1202 	A_FREE(stp);
1203 	if(status != NC_NOERR)
1204 	{
1205 		nc_advise("ncvargets", status, "ncid %d", ncid);
1206 		return -1;
1207 	}
1208 	}
1209 	return 0;
1210 	}
1211 }
1212 
1213 /** \ingroup v2_api
1214 
1215 Write mapped data.
1216 
1217 This is part of the legacy V2 API of netCDF. New code should be
1218 written with the V3 API. See V3 function nc_get_varm().
1219 
1220 \param ncid file ID
1221 \param varid the variable ID.
1222 \param start pointer to array of start values.
1223 \param count pointer to array of count values.
1224 \param stride pointer to array of stride values.
1225 \param map pointer to array of map values.
1226 \param value pointer to data.
1227 
1228 \returns 0 for success or -1 for failure.
1229 */
1230 int
ncvarputg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,const void * value)1231 ncvarputg(
1232     int		ncid,
1233     int		varid,
1234     const long*	start,
1235     const long*	count,
1236     const long*	stride,
1237     const long*	map,
1238     const void* value
1239 )
1240 {
1241 	int ndims = 0;
1242 	if(map == NULL)
1243 		return ncvarputs(ncid, varid, start, count, stride, value);
1244 	/* else */
1245 	{
1246 	ptrdiff_t *imp=NULL;
1247 	if (map != NULL) {
1248 		int ret = NC_NOERR;
1249 		/* make map[ndims-1] number of elements instead of bytes */
1250 		int i, el_size;
1251 		nc_type type;
1252 		ret = nc_inq_varndims(ncid, varid, &ndims);
1253 		if(ret) return ret;
1254 		ret = nc_inq_vartype(ncid, varid, &type);
1255 		if(ret) return ret;
1256 				el_size = nctypelen(type);
1257 		imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
1258 		for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
1259 	}
1260 
1261 	{
1262 	A_DECL(stp, size_t, ndims, start);
1263 	A_DECL(cntp, size_t, ndims, count);
1264 	A_DECL(strdp, ptrdiff_t, ndims, stride);
1265 	A_INIT(stp, size_t, ndims, start);
1266 	A_INIT(cntp, size_t, ndims, count);
1267 	A_INIT(strdp, ptrdiff_t, ndims, stride);
1268 	{
1269 	const int status = nc_put_varm(ncid, varid,
1270 			 stp, cntp, strdp, imp, value);
1271 	if (imp!=NULL) free(imp);
1272 	A_FREE(strdp);
1273 	A_FREE(cntp);
1274 	A_FREE(stp);
1275 	if(status != NC_NOERR)
1276 	{
1277 		nc_advise("ncvarputg", status, "ncid %d", ncid);
1278 		return -1;
1279 	}
1280 	}
1281 	return 0;
1282 	}
1283 	}
1284 }
1285 
1286 /** \ingroup v2_api
1287 
1288 Read mapped data.
1289 
1290 This is part of the legacy V2 API of netCDF. New code should be
1291 written with the V3 API. See V3 function nc_get_varm().
1292 
1293 \param ncid file ID
1294 \param varid the variable ID.
1295 \param start pointer to array of start values.
1296 \param count pointer to array of count values.
1297 \param stride pointer to array of stride values.
1298 \param map pointer to array of map values.
1299 \param value pointer to data.
1300 
1301 \returns 0 for success or -1 for failure.
1302 */
1303 int
ncvargetg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,void * value)1304 ncvargetg(
1305     int		ncid,
1306     int		varid,
1307     const long*	start,
1308     const long*	count,
1309     const long*	stride,
1310     const long*	map,
1311     void*	value
1312 )
1313 {
1314 	int ndims = 0;
1315 	if(map == NULL)
1316 		return ncvargets(ncid, varid, start, count, stride, value);
1317 	/* else */
1318 	{
1319 	ptrdiff_t *imp=NULL;
1320 	if (map != NULL) {
1321 		int ret = NC_NOERR;
1322 		/* make map[ndims-1] number of elements instead of bytes */
1323 		int i, el_size;
1324 		nc_type type;
1325 		ret = nc_inq_varndims(ncid, varid, &ndims);
1326 		if(ret) return ret;
1327 		ret = nc_inq_vartype(ncid, varid, &type);
1328 		if(ret) return ret;
1329 		el_size = nctypelen(type);
1330 		imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
1331 		for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
1332 	}
1333 
1334 	{
1335 	A_DECL(stp, size_t, ndims, start);
1336 	A_DECL(cntp, size_t, ndims, count);
1337 	A_DECL(strdp, ptrdiff_t, ndims, stride);
1338 	A_INIT(stp, size_t, ndims, start);
1339 	A_INIT(cntp, size_t, ndims, count);
1340 	A_INIT(strdp, ptrdiff_t, ndims, stride);
1341 	{
1342 	const int status = nc_get_varm(ncid, varid,
1343 			stp, cntp, strdp, imp, value);
1344 	if (imp!=NULL) free(imp);
1345 	A_FREE(strdp);
1346 	A_FREE(cntp);
1347 	A_FREE(stp);
1348 	if(status != NC_NOERR)
1349 	{
1350 		nc_advise("ncvargetg", status, "ncid %d", ncid);
1351 		return -1;
1352 	}
1353 	}
1354 	return 0;
1355 	}
1356 	}
1357 }
1358 
1359 /** \ingroup v2_api
1360 
1361 Rename a variable.
1362 
1363 This is part of the legacy V2 API of netCDF. New code should be
1364 written with the V3 API. See V3 function nc_rename_var().
1365 
1366 \param ncid file ID
1367 \param varid the variable ID.
1368 \param name the new name.
1369 
1370 \returns varid or -1 for failure.
1371 */
1372 int
ncvarrename(int ncid,int varid,const char * name)1373 ncvarrename(
1374     int		ncid,
1375     int		varid,
1376     const char*	name
1377 )
1378 {
1379 	const int status = nc_rename_var(ncid, varid, name);
1380 	if(status != NC_NOERR)
1381 	{
1382 		nc_advise("ncvarrename", status, "ncid %d", ncid);
1383 		return -1;
1384 	}
1385 	return varid;
1386 }
1387 
1388 /** \ingroup v2_api
1389 
1390 Write an attribute.
1391 
1392 This is part of the legacy V2 API of netCDF. New code should be
1393 written with the V3 API. See V3 function nc_put_att_int(), etc.
1394 
1395 \param ncid file ID
1396 \param varid the variable ID or NC_GLOBAL.
1397 \param name the name of the attribute.
1398 \param datatype the type of the attribute.
1399 \param len the length of the attribute.
1400 \param value the attribute value.
1401 
1402 \returns dimid or -1 for failure.
1403 */
1404 int
ncattput(int ncid,int varid,const char * name,nc_type datatype,int len,const void * value)1405 ncattput(
1406     int		ncid,
1407     int		varid,
1408     const char*	name,
1409     nc_type	datatype,
1410     int		len,
1411     const void*	value
1412 )
1413 {
1414 	const int status = nc_put_att(ncid, varid, name, datatype, len, value);
1415 	if(status != NC_NOERR)
1416 	{
1417 		nc_advise("ncattput", status, "ncid %d", ncid);
1418 		return -1;
1419 	}
1420 	return 0;
1421 }
1422 
1423 /** \ingroup v2_api
1424 
1425 Learn about an attribute.
1426 
1427 This is part of the legacy V2 API of netCDF. New code should be
1428 written with the V3 API. See V3 function nc_inq_att().
1429 
1430 \param ncid file ID
1431 \param varid the variable ID.
1432 \param name the name of the attribute.
1433 \param datatype pointer that will get data type.
1434 \param len pointer that will get length.
1435 
1436 \returns 1 for success or -1 for failure. (That's a delightful
1437 artifact of a by-gone era of C programming, isn't it?)
1438 */
1439 int
ncattinq(int ncid,int varid,const char * name,nc_type * datatype,int * len)1440 ncattinq(
1441     int		ncid,
1442     int		varid,
1443     const char*	name,
1444     nc_type*	datatype,
1445     int*	len
1446 )
1447 {
1448 	size_t ll;
1449 	const int status = nc_inq_att(ncid, varid, name, datatype, &ll);
1450 	if(status != NC_NOERR)
1451 	{
1452 		nc_advise("ncattinq", status,
1453 		    "ncid %d; varid %d; attname \"%s\"",
1454 		    ncid, varid, name);
1455 		return -1;
1456 	}
1457 
1458 	if(len != NULL)
1459 		*len = (int) ll;
1460 
1461 	return 1;
1462 }
1463 
1464 /** \ingroup v2_api
1465 
1466 Read an attribute.
1467 
1468 This is part of the legacy V2 API of netCDF. New code should be
1469 written with the V3 API. See V3 function nc_get_att_int(), etc.
1470 
1471 \param ncid file ID.
1472 \param varid the variable ID or NC_GLOBAL.
1473 \param name the name of the attribute.
1474 \param value pointer that will get the attribute data.
1475 
1476 \returns 1 for success or -1 for failure.
1477 */
1478 int
ncattget(int ncid,int varid,const char * name,void * value)1479 ncattget(
1480     int		ncid,
1481     int		varid,
1482     const char*	name,
1483     void*	value
1484 )
1485 {
1486 	const int status = nc_get_att(ncid, varid, name, value);
1487 	if(status != NC_NOERR)
1488 	{
1489 		nc_advise("ncattget", status, "ncid %d", ncid);
1490 		return -1;
1491 	}
1492 	return 1;
1493 }
1494 
1495 /** \ingroup v2_api
1496 
1497 Copy an attribute.
1498 
1499 This is part of the legacy V2 API of netCDF. New code should be
1500 written with the V3 API. See V3 function nc_get_att_int(), etc.
1501 
1502 \param ncid_in file ID to copy from.
1503 \param varid_in the variable ID or NC_GLOBAL to copy from.
1504 \param name the name of the attribute.
1505 \param ncid_out file ID to copy to.
1506 \param varid_out the variable ID or NC_GLOBAL to copy to.
1507 
1508 \returns 0 for success or -1 for failure.
1509 */
1510 int
ncattcopy(int ncid_in,int varid_in,const char * name,int ncid_out,int varid_out)1511 ncattcopy(
1512     int		ncid_in,
1513     int		varid_in,
1514     const char*	name,
1515     int		ncid_out,
1516     int		varid_out
1517 )
1518 {
1519 	const int status = nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out);
1520 	if(status != NC_NOERR)
1521 	{
1522 		nc_advise("ncattcopy", status, "%s", name);
1523 		return -1;
1524 	}
1525 	return 0;
1526 }
1527 
1528 /** \ingroup v2_api
1529 
1530 Learn attribute name from its number.
1531 
1532 This is part of the legacy V2 API of netCDF. New code should be
1533 written with the V3 API. See V3 function nc_inq_attname().
1534 
1535 \param ncid file ID
1536 \param varid the variable ID.
1537 \param attnum the number of the attribute.
1538 \param name the name of the attribute.
1539 
1540 \returns attnum for success or -1 for failure.
1541 */
1542 int
ncattname(int ncid,int varid,int attnum,char * name)1543 ncattname(
1544     int		ncid,
1545     int		varid,
1546     int		attnum,
1547     char*	name
1548 )
1549 {
1550 	const int status = nc_inq_attname(ncid, varid, attnum, name);
1551 	if(status != NC_NOERR)
1552 	{
1553 		nc_advise("ncattname", status, "ncid %d", ncid);
1554 		return -1;
1555 	}
1556 	return attnum;
1557 }
1558 
1559 /** \ingroup v2_api
1560 
1561 Rename an attribute.
1562 
1563 This is part of the legacy V2 API of netCDF. New code should be
1564 written with the V3 API. See V3 function nc_rename_att().
1565 
1566 \param ncid file ID
1567 \param varid the variable ID.
1568 \param name the attribute name.
1569 \param newname the new name.
1570 
1571 \returns 1 for success or -1 for failure.
1572 */
1573 int
ncattrename(int ncid,int varid,const char * name,const char * newname)1574 ncattrename(
1575     int		ncid,
1576     int		varid,
1577     const char*	name,
1578     const char*	newname
1579 )
1580 {
1581 	const int status = nc_rename_att(ncid, varid, name, newname);
1582 	if(status != NC_NOERR)
1583 	{
1584 		nc_advise("ncattrename", status, "ncid %d", ncid);
1585 		return -1;
1586 	}
1587 	return 1;
1588 }
1589 
1590 /** \ingroup v2_api
1591 
1592 Delete an attribute.
1593 
1594 This is part of the legacy V2 API of netCDF. New code should be
1595 written with the V3 API. See V3 function nc_delete_att().
1596 
1597 \param ncid file ID
1598 \param varid the variable ID.
1599 \param name the attribute name.
1600 
1601 \returns 1 for success or -1 for failure.
1602 */
1603 int
ncattdel(int ncid,int varid,const char * name)1604 ncattdel(
1605     int		ncid,
1606     int		varid,
1607     const char*	name
1608 )
1609 {
1610 	 const int status = nc_del_att(ncid, varid, name);
1611 	if(status != NC_NOERR)
1612 	{
1613 		nc_advise("ncattdel", status, "ncid %d", ncid);
1614 		return -1;
1615 	}
1616 	return 1;
1617 }
1618 
1619 #endif /* NO_NETCDF_2 */
1620 
1621 #ifndef NO_NETCDF_2
1622 
1623 /** \ingroup v2_api
1624 
1625 Set the fill mode.
1626 
1627 This is part of the legacy V2 API of netCDF. New code should be
1628 written with the V3 API. See V3 function nc_set_fill().
1629 
1630 \param ncid file ID
1631 \param fillmode NC_FILL or NC_NOFILL.
1632 
1633 \returns oldmode for success or -1 for failure.
1634 */
1635 int
ncsetfill(int ncid,int fillmode)1636 ncsetfill(
1637     int		ncid,
1638     int		fillmode
1639 )
1640 {
1641 	int oldmode = -1;
1642 	const int status = nc_set_fill(ncid, fillmode, &oldmode);
1643 	if(status != NC_NOERR)
1644 	{
1645 		nc_advise("ncsetfill", status, "ncid %d", ncid);
1646 		return -1;
1647 	}
1648 	return oldmode;
1649 }
1650 
1651 /** \ingroup v2_api
1652 
1653 Learn record variables and the lengths of the record dimension.
1654 
1655 This is part of the legacy V2 API of netCDF. New code should be
1656 written with the V3 API. See V3 functions nc_inq_var()/nc_inq_dim().
1657 
1658 \param ncid file ID
1659 \param nrecvars pointer that will get number of record variables.
1660 \param recvarids pointer that will get array of record variable IDs.
1661 \param recsizes pointer that will get array of record dimension length.
1662 
1663 \returns oldmode for success or -1 for failure.
1664 */
1665 int
ncrecinq(int ncid,int * nrecvars,int * recvarids,long * recsizes)1666 ncrecinq(
1667     int		ncid,
1668     int*	nrecvars,
1669     int*	recvarids,
1670     long*	recsizes
1671 )
1672 {
1673 	size_t nrv = 0;
1674 	size_t *rs = NULL;
1675 	int status = NC_NOERR;
1676 
1677 	rs = (size_t*)malloc(sizeof(size_t)*NC_MAX_VARS);
1678 	if(rs == NULL)
1679 	    return NC_ENOMEM;
1680 
1681 	status = nc_inq_rec(ncid, &nrv, recvarids, rs);
1682 	if(status != NC_NOERR)
1683 	{
1684 		nc_advise("ncrecinq", status, "ncid %d", ncid);
1685 		if(rs != NULL) free(rs);
1686 		return -1;
1687 	}
1688 
1689 	if(nrecvars != NULL)
1690 		*nrecvars = (int) nrv;
1691 
1692 	if(recsizes != NULL)
1693 	{
1694 		size_t ii;
1695 		for(ii = 0; ii < nrv; ii++)
1696 		{
1697 			recsizes[ii] = (long) rs[ii];
1698 		}
1699 	}
1700 
1701 	if(rs != NULL) free(rs);
1702 
1703 	return (int) nrv;
1704 }
1705 
1706 /** \ingroup v2_api
1707 
1708 Read one record's worth of data, except don't read from variables for which
1709 the address of the data to be read is null.  Return -1 on error. This is
1710 the same as the nc_get_rec(), with poorer error handling.
1711 
1712 This is part of the legacy V2 API of netCDF. New code should be
1713 written with the V3 API. See V3 function nc_get_vara().
1714 
1715 \param ncid file ID
1716 \param recnum the record number to read.
1717 \param datap pointer memory to hold one record's worth of data for all
1718 variables.
1719 
1720 \returns 0 for success, -1 for error.
1721 */
1722 int
ncrecget(int ncid,long recnum,void ** datap)1723 ncrecget(
1724     int		ncid,
1725     long	recnum,
1726     void**	datap
1727 )
1728 {
1729 	const int status = nc_get_rec(ncid, (size_t)recnum, datap);
1730 	if(status != NC_NOERR)
1731 	{
1732 		nc_advise("ncrecget", status, "ncid %d", ncid);
1733 		return -1;
1734 	}
1735 	return 0;
1736 }
1737 
1738 /** \ingroup v2_api
1739 
1740 Write one record's worth of data, except don't write to variables for which
1741 the address of the data to be written is NULL.  Return -1 on error.  This is
1742 the same as the nc_put_rec(), but with poorer error handling.
1743 
1744 This is part of the legacy V2 API of netCDF. New code should be
1745 written with the V3 API. See V3 function nc_put_vara().
1746 
1747 \param ncid file ID
1748 \param recnum the record number to write.
1749 \param datap pointer to one record's worth of data for all variables.
1750 
1751 \returns 0 for success, -1 for error.
1752 */
1753 int
ncrecput(int ncid,long recnum,void * const * datap)1754 ncrecput(
1755     int		ncid,
1756     long	recnum,
1757     void* const* datap
1758 )
1759 {
1760 	const int status = nc_put_rec(ncid, (size_t)recnum, datap);
1761 	if(status != NC_NOERR)
1762 	{
1763 		nc_advise("ncrecput", status, "ncid %d", ncid);
1764 		return -1;
1765 	}
1766 	return 0;
1767 }
1768 
1769 #endif /* NO_NETCDF_2 */
1770