1 /*
2  *	Copyright 1996, University Corporation for Atmospheric Research
3  *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  */
5 /* $Id: v2i.c,v 1.52 2009/02/20 22:00:46 dmh Exp $ */
6 
7 #ifndef NO_NETCDF_2
8 
9 #include <config.h>
10 #include <stdlib.h>
11 #ifndef NO_SYS_TYPES_H
12 #  include <sys/types.h> /* Keep before xxxnetcdf.h or Win64 gets confused. */
13 #endif /* NO_SYS_TYPES_H */
14 #include "nc.h" /* WARNING: nc.h must be included before xxxnetcdf.h or MSVC60 will die. */
15 #include "xxxnetcdf.h"
16 
17 #if SIZEOF_LONG == SIZEOF_SIZE_T
18 /*
19  * We don't have to copy the arguments to switch from 'long'
20  * to 'size_t' or 'ptrdiff_t'. Use dummy macros.
21  */
22 
23 # define NDIMS_DECL
24 # define A_DECL(name, type, ndims, rhs) \
25 	const type *const name = ((const type *)(rhs))
26 
27 # define A_FREE(name)
28 
29 # define A_INIT(lhs, type, ndims, rhs)
30 
31 #else
32 /*
33  * We do have to copy the arguments to switch from 'long'
34  * to 'size_t' or 'ptrdiff_t'. In my tests on an SGI,
35  * any additional cost was lost in measurement variation.
36  */
37 
38 # include "onstack.h"
39 
40 static size_t
nvdims(int ncid,int varid)41 nvdims(int ncid, int varid)
42 {
43 	NC *ncp;
44 	if(NC_check_id(ncid, &ncp) != NC_NOERR)
45 		return 0;
46 	{
47 		const NC_var *const varp = NC_lookupvar(ncp, varid);
48 		if(varp == NULL)
49 			return 0;
50 		return varp->ndims;
51 	}
52 }
53 
54 #define NDIMS_DECL	const size_t ndims = nvdims(ncid, varid);
55 
56 # define A_DECL(name, type, ndims, rhs) \
57 	ALLOC_ONSTACK(name, type, ndims)
58 
59 # define A_FREE(name) \
60 	FREE_ONSTACK(name)
61 
62 # define A_INIT(lhs, type, ndims, rhs) \
63 	{ \
64 		const long *lp = rhs; \
65 		type *tp = lhs; \
66 		type *const end = lhs + ndims; \
67 		while(tp < end) \
68 		{ \
69 			*tp++ = (type) *lp++; \
70 		} \
71 	}
72 
73 
74 #endif
75 
76 /*
77  * Computes number of record variables in an open netCDF file, and an array of
78  * the record variable ids, if the array parameter is non-null.
79  */
80 static int
numrecvars(int ncid,int * nrecvarsp,int * recvarids)81 numrecvars(int ncid, int *nrecvarsp, int *recvarids)
82 {
83     int status;
84     int nvars = 0;
85     int ndims = 0;
86     int nrecvars = 0;
87     int varid;
88     int recdimid;
89     int dimids[MAX_NC_DIMS];
90 
91     status = nc_inq_nvars(ncid, &nvars);
92     if(status != NC_NOERR)
93 	return status;
94 
95     status = nc_inq_unlimdim(ncid, &recdimid);
96     if(status != NC_NOERR)
97 	return status;
98 
99     if (recdimid == -1) {
100 	*nrecvarsp = 0;
101 	return NC_NOERR;
102     }
103     nrecvars = 0;
104     for (varid = 0; varid < nvars; varid++) {
105 	status = nc_inq_varndims(ncid, varid, &ndims);
106 	if(status != NC_NOERR)
107 	    return status;
108 	status = nc_inq_vardimid(ncid, varid, dimids);
109 	if(status != NC_NOERR)
110 	    return status;
111 	if (ndims > 0 && dimids[0] == recdimid) {
112 	    if (recvarids != NULL)
113 	      recvarids[nrecvars] = varid;
114 	    nrecvars++;
115 	}
116     }
117     *nrecvarsp = nrecvars;
118     return NC_NOERR;
119 }
120 
121 
122 /*
123  * Computes record size (in bytes) of the record variable with a specified
124  * variable id.  Returns size as 0 if not a record variable.
125  */
126 static int
ncrecsize(int ncid,int varid,size_t * recsizep)127 ncrecsize(int ncid, int varid, size_t *recsizep)
128 {
129     int status;
130     int recdimid;
131     nc_type type;
132     int ndims;
133     int dimids[MAX_NC_DIMS];
134     int id;
135     size_t size;
136 
137     *recsizep = 0;
138     status = nc_inq_unlimdim(ncid, &recdimid);
139     if(status != NC_NOERR)
140 	return status;
141     status = nc_inq_vartype(ncid, varid, &type);
142     if(status != NC_NOERR)
143 	return status;
144     status = nc_inq_varndims(ncid, varid, &ndims);
145     if(status != NC_NOERR)
146 	return status;
147     status = nc_inq_vardimid(ncid, varid, dimids);
148     if(status != NC_NOERR)
149 	return status;
150     if (ndims == 0 || dimids[0] != recdimid) {
151 	return NC_NOERR;
152     }
153     size = nctypelen(type);
154     for (id = 1; id < ndims; id++) {
155 	size_t len;
156 	status = nc_inq_dimlen(ncid, dimids[id], &len);
157 	if(status != NC_NOERR)
158 		return status;
159 	size *= len;
160     }
161     *recsizep = size;
162     return NC_NOERR;
163 }
164 
165 
166 /*
167  * Retrieves the dimension sizes of a variable with a specified variable id in
168  * an open netCDF file.  Returns -1 on error.
169  */
170 static int
dimsizes(int ncid,int varid,size_t * sizes)171 dimsizes(int ncid, int varid, size_t *sizes)
172 {
173     int status;
174     int ndims;
175     int id;
176     int dimids[MAX_NC_DIMS];
177 
178     status = nc_inq_varndims(ncid, varid, &ndims);
179     if(status != NC_NOERR)
180 	return status;
181     status = nc_inq_vardimid(ncid, varid, dimids);
182     if(status != NC_NOERR)
183 	return status;
184     if (ndims == 0 || sizes == NULL)
185       return NC_NOERR;
186     for (id = 0; id < ndims; id++) {
187 	size_t len;
188 	status = nc_inq_dimlen(ncid, dimids[id], &len);
189 	if(status != NC_NOERR)
190 		return status;
191 	sizes[id] = len;
192     }
193     return NC_NOERR;
194 }
195 
196 
197 /*
198  * Retrieves the number of record variables, the record variable ids, and the
199  * record size of each record variable.  If any pointer to info to be returned
200  * is null, the associated information is not returned.  Returns -1 on error.
201  */
202 int
nc_inq_rec(int ncid,size_t * nrecvarsp,int * recvarids,size_t * recsizes)203 nc_inq_rec(
204 	int ncid,
205 	size_t *nrecvarsp,
206 	int *recvarids,
207 	size_t *recsizes)
208 {
209     int status;
210     int nvars = 0;
211     int recdimid;
212     int varid;
213     int rvarids[MAX_NC_VARS];
214     int nrvars = 0;
215 
216     status = nc_inq_nvars(ncid, &nvars);
217     if(status != NC_NOERR)
218 	return status;
219 
220     status = nc_inq_unlimdim(ncid, &recdimid);
221     if(status != NC_NOERR)
222 	return status;
223 
224     *nrecvarsp = 0;
225     if (recdimid == -1)
226 	return NC_NOERR;
227 
228     status = numrecvars(ncid, &nrvars, rvarids);
229     if(status != NC_NOERR)
230 	return status;
231 
232     if (nrecvarsp != NULL)
233 	*nrecvarsp = nrvars;
234     if (recvarids != NULL)
235 	for (varid = 0; varid < nrvars; varid++)
236 	    recvarids[varid] = rvarids[varid];
237 
238     if (recsizes != NULL)
239 	for (varid = 0; varid < nrvars; varid++) {
240 	    size_t rsize;
241 	    status = ncrecsize(ncid, rvarids[varid], &rsize);
242 	    if (status != NC_NOERR)
243 		return status;
244 	    recsizes[varid] = rsize;
245 	}
246 	return NC_NOERR;
247 }
248 
249 
250 /*
251  * Write one record's worth of data, except don't write to variables for which
252  * the address of the data to be written is NULL.  Return -1 on error.  This is
253  * the same as the ncrecput() in the library, except that can handle errors
254  * better.
255  */
256 int
nc_put_rec(int ncid,size_t recnum,void * const * datap)257 nc_put_rec(
258 	int ncid,
259 	size_t recnum,
260 	void* const* datap)
261 {
262     int status;
263     int varid;
264     int rvarids[MAX_NC_VARS];
265     int nrvars;
266     size_t start[MAX_NC_DIMS];
267     size_t edges[MAX_NC_DIMS];
268 
269     status = numrecvars(ncid, &nrvars, rvarids);
270     if(status != NC_NOERR)
271 	return status;
272 
273     if (nrvars == 0)
274       return NC_NOERR;
275 
276     start[0] = recnum;
277     for (varid = 1; varid < nrvars; varid++)
278 	start[varid] = 0;
279 
280     for (varid = 0; varid < nrvars; varid++) {
281 	if (datap[varid] != NULL) {
282 	    status = dimsizes(ncid, rvarids[varid], edges);
283 	    if(status != NC_NOERR)
284 		return status;
285 
286 	    edges[0] = 1;		/* only 1 record's worth */
287 	    status = nc_put_vara(ncid, rvarids[varid], start, edges, datap[varid]);
288 	    if(status != NC_NOERR)
289 		return status;
290 	}
291     }
292     return 0;
293 }
294 
295 
296 /*
297  * Read one record's worth of data, except don't read from variables for which
298  * the address of the data to be read is null.  Return -1 on error.  This is
299  * the same as the ncrecget() in the library, except that can handle errors
300  * better.
301  */
302 int
nc_get_rec(int ncid,size_t recnum,void ** datap)303 nc_get_rec(
304 	int ncid,
305 	size_t recnum,
306 	void **datap)
307 {
308     int status;
309     int varid;
310     int rvarids[MAX_NC_VARS];
311     int nrvars;
312     size_t start[MAX_NC_DIMS];
313     size_t edges[MAX_NC_DIMS];
314 
315     status = numrecvars(ncid, &nrvars, rvarids);
316     if(status != NC_NOERR)
317 	return status;
318 
319     if (nrvars == 0)
320       return NC_NOERR;
321 
322     start[0] = recnum;
323     for (varid = 1; varid < nrvars; varid++)
324 	start[varid] = 0;
325 
326     for (varid = 0; varid < nrvars; varid++) {
327 	if (datap[varid] != NULL) {
328 	    status = dimsizes(ncid, rvarids[varid], edges);
329 	    if(status != NC_NOERR)
330 		return status;
331 	    edges[0] = 1;		/* only 1 record's worth */
332 	    status = nc_get_vara(ncid, rvarids[varid], start, edges, datap[varid]);
333 	    if(status != NC_NOERR)
334 		return status;
335 	}
336     }
337     return 0;
338 }
339 
340 
341 /* Begin globals */
342 
343 /*
344  * Error code
345  */
346 int ncerr = NC_NOERR ;
347 
348 
349 /*
350  * The subroutines in error.c emit no messages unless NC_VERBOSE bit is on.
351  * They call exit() when NC_FATAL bit is on.
352  */
353 int ncopts = (NC_FATAL | NC_VERBOSE) ;
354 
355 /* End globals */
356 
357 /* Begin error handling */
358 
359 #include <stdio.h>
360 #include <stdlib.h>
361 #include <stdarg.h>
362 
363 /*
364  */
365 void
nc_advise(const char * routine_name,int err,const char * fmt,...)366 nc_advise(const char *routine_name, int err, const char *fmt,...)
367 {
368 	va_list args;
369 
370 	if(NC_ISSYSERR(err))
371 		ncerr = NC_SYSERR;
372 	else
373 		ncerr = err;
374 
375 	if( ncopts & NC_VERBOSE )
376 	{
377 		(void) fprintf(stderr,"%s: ", routine_name);
378 		va_start(args ,fmt);
379 		(void) vfprintf(stderr,fmt,args);
380 		va_end(args);
381 		if(err != NC_NOERR)
382 		{
383 			(void) fprintf(stderr,": %s",
384 				nc_strerror(err));
385 		}
386 		(void) fputc('\n',stderr);
387 		(void) fflush(stderr);	/* to ensure log files are current */
388 	}
389 
390 	if( (ncopts & NC_FATAL) && err != NC_NOERR )
391 	{
392 		exit(ncopts);
393 	}
394 }
395 
396 /* End error handling */
397 
398 int
nccreate(const char * path,int cmode)399 nccreate(const char* path, int cmode)
400 {
401 	int ncid;
402 	const int status = nc_create(path, cmode, &ncid);
403 	if(status != NC_NOERR)
404 	{
405 		nc_advise("nccreate", status, "filename \"%s\"", path);
406 		return -1;
407 	}
408 	return ncid;
409 }
410 
411 
412 int
ncopen(const char * path,int mode)413 ncopen(const char *path, int mode)
414 {
415 	int ncid;
416 	const int status = nc_open(path, mode, &ncid);
417 	if(status != NC_NOERR)
418 	{
419 		nc_advise("ncopen", status, "filename \"%s\"", path);
420 		return -1;
421 	}
422 	return ncid;
423 }
424 
425 
426 int
ncredef(int ncid)427 ncredef(int ncid)
428 {
429 	const int status =  nc_redef(ncid);
430 	if(status != NC_NOERR)
431 	{
432 		nc_advise("ncredef", status, "ncid %d", ncid);
433 		return -1;
434 	}
435 	return 0;
436 }
437 
438 
439 int
ncendef(int ncid)440 ncendef(int ncid)
441 {
442 	const int status = nc_enddef(ncid);
443 	if(status != NC_NOERR)
444 	{
445 		nc_advise("ncendef", status, "ncid %d", ncid);
446 		return -1;
447 	}
448 	return 0;
449 }
450 
451 
452 int
ncclose(int ncid)453 ncclose(int ncid)
454 {
455 	const int status = nc_close(ncid);
456 	if(status != NC_NOERR)
457 	{
458 		nc_advise("ncclose", status, "ncid %d", ncid);
459 		return -1;
460 
461 	}
462 	return 0;
463 }
464 
465 
466 int
ncinquire(int ncid,int * ndims,int * nvars,int * natts,int * recdim)467 ncinquire(
468     int		ncid,
469     int*	ndims,
470     int*	nvars,
471     int*	natts,
472     int*	recdim
473 )
474 {
475 	int nd, nv, na;
476 	const int status = nc_inq(ncid, &nd, &nv, &na, recdim);
477 
478 	if(status != NC_NOERR)
479 	{
480 		nc_advise("ncinquire", status, "ncid %d", ncid);
481 		return -1;
482 	}
483 	/* else */
484 
485 	if(ndims != NULL)
486 		*ndims = (int) nd;
487 
488 	if(nvars != NULL)
489 		*nvars = (int) nv;
490 
491 	if(natts != NULL)
492 		*natts = (int) na;
493 
494 	return ncid;
495 }
496 
497 
498 int
ncsync(int ncid)499 ncsync(int ncid)
500 {
501 	const int status = nc_sync(ncid);
502 	if(status != NC_NOERR)
503 	{
504 		nc_advise("ncsync", status, "ncid %d", ncid);
505 		return -1;
506 
507 	}
508 	return 0;
509 }
510 
511 
512 int
ncabort(int ncid)513 ncabort(int ncid)
514 {
515 	const int status = nc_abort(ncid);
516 	if(status != NC_NOERR)
517 	{
518 		nc_advise("ncabort", status, "ncid %d", ncid);
519 		return -1;
520 	}
521 	return 0;
522 }
523 
524 
525 int
ncdimdef(int ncid,const char * name,long length)526 ncdimdef(
527     int		ncid,
528     const char*	name,
529     long	length
530 )
531 {
532 	int dimid;
533 	int status;
534 	if(length < 0) {
535 	    status = NC_EDIMSIZE;
536 	    nc_advise("ncdimdef", status, "ncid %d", ncid);
537 	    return -1;
538 	}
539 	status =  nc_def_dim(ncid, name, (size_t)length, &dimid);
540 	if(status != NC_NOERR)
541 	{
542 		nc_advise("ncdimdef", status, "ncid %d", ncid);
543 		return -1;
544 	}
545 	return dimid;
546 }
547 
548 
549 int
ncdimid(int ncid,const char * name)550 ncdimid(int ncid, const char*	name)
551 {
552 	int dimid;
553 	const int status =  nc_inq_dimid(ncid, name, &dimid);
554 	if(status != NC_NOERR)
555 	{
556 		nc_advise("ncdimid", status, "ncid %d", ncid);
557 		return -1;
558 	}
559 	return dimid;
560 }
561 
562 
563 int
ncdiminq(int ncid,int dimid,char * name,long * length)564 ncdiminq(
565     int		ncid,
566     int		dimid,
567     char*	name,
568     long*	length
569 )
570 {
571 	size_t ll;
572 	const int status = nc_inq_dim(ncid, dimid, name, &ll);
573 
574 	if(status != NC_NOERR)
575 	{
576 		nc_advise("ncdiminq", status, "ncid %d", ncid);
577 		return -1;
578 	}
579 	/* else */
580 
581 	if(length != NULL)
582 		*length = (int) ll;
583 
584 	return dimid;
585 }
586 
587 
588 int
ncdimrename(int ncid,int dimid,const char * name)589 ncdimrename(
590     int		ncid,
591     int		dimid,
592     const char*	name
593 )
594 {
595 	const int status = nc_rename_dim(ncid, dimid, name);
596 	if(status != NC_NOERR)
597 	{
598 		nc_advise("ncdimrename", status, "ncid %d", ncid);
599 		return -1;
600 	}
601 	return dimid;
602 }
603 
604 
605 int
ncvardef(int ncid,const char * name,nc_type datatype,int ndims,const int * dim)606 ncvardef(
607     int		ncid,
608     const char*	name,
609     nc_type	datatype,
610     int		ndims,
611     const int*	dim
612 )
613 {
614 	int varid = -1;
615 	const int status = nc_def_var(ncid, name, datatype, ndims, dim, &varid);
616 	if(status != NC_NOERR)
617 	{
618 		nc_advise("ncvardef", status, "ncid %d", ncid);
619 		return -1;
620 	}
621 	return varid;
622 }
623 
624 
625 int
ncvarid(int ncid,const char * name)626 ncvarid(
627     int		ncid,
628     const char*	name
629 )
630 {
631 	int varid = -1;
632 	const int status = nc_inq_varid(ncid, name, &varid);
633 	if(status != NC_NOERR)
634 	{
635 		nc_advise("ncvarid", status, "ncid %d", ncid);
636 		return -1;
637 	}
638 	return varid;
639 }
640 
641 
642 int
ncvarinq(int ncid,int varid,char * name,nc_type * datatype,int * ndims,int * dim,int * natts)643 ncvarinq(
644     int		ncid,
645     int		varid,
646     char*	name,
647     nc_type*	datatype,
648     int*	ndims,
649     int*	dim,
650     int*	natts
651 )
652 {
653 	int nd, na;
654 	const int status = nc_inq_var(ncid, varid, name, datatype,
655 		 &nd, dim, &na);
656 
657 	if(status != NC_NOERR)
658 	{
659 		nc_advise("ncvarinq", status, "ncid %d", ncid);
660 		return -1;
661 	}
662 	/* else */
663 
664 	if(ndims != NULL)
665 		*ndims = (int) nd;
666 
667 	if(natts != NULL)
668 		*natts = (int) na;
669 
670 	return varid;
671 }
672 
673 
674 int
ncvarput1(int ncid,int varid,const long * index,const void * value)675 ncvarput1(
676     int		ncid,
677     int		varid,
678     const long*	index,
679     const void*	value
680 )
681 {
682 	NDIMS_DECL
683 	A_DECL(coordp, size_t, ndims, index);
684 	A_INIT(coordp, size_t, ndims, index);
685 	{
686 	const int status = nc_put_var1(ncid, varid, coordp, value);
687 	A_FREE(coordp);
688 	if(status != NC_NOERR)
689 	{
690 		nc_advise("ncvarput1", status, "ncid %d", ncid);
691 		return -1;
692 	}
693 	}
694 	return 0;
695 }
696 
697 
698 int
ncvarget1(int ncid,int varid,const long * index,void * value)699 ncvarget1(
700     int		ncid,
701     int		varid,
702     const long*	index,
703     void*	value
704 )
705 {
706 	NDIMS_DECL
707 	A_DECL(coordp, size_t, ndims, index);
708 	A_INIT(coordp, size_t, ndims, index);
709 	{
710 	const int status = nc_get_var1(ncid, varid, coordp, value);
711 	A_FREE(coordp);
712 	if(status != NC_NOERR)
713 	{
714 		nc_advise("ncdimid", status, "ncid %d", ncid);
715 		return -1;
716 	}
717 	}
718 	return 0;
719 }
720 
721 
722 int
ncvarput(int ncid,int varid,const long * start,const long * count,const void * value)723 ncvarput(
724     int		ncid,
725     int		varid,
726     const long*	start,
727     const long*	count,
728     const void*	value
729 )
730 {
731 	NDIMS_DECL
732 	A_DECL(stp, size_t, ndims, start);
733 	A_DECL(cntp, size_t, ndims, count);
734 	A_INIT(stp, size_t, ndims, start);
735 	A_INIT(cntp, size_t, ndims, count);
736 	{
737 	const int status = nc_put_vara(ncid, varid, stp, cntp, value);
738 	A_FREE(cntp);
739 	A_FREE(stp);
740 	if(status != NC_NOERR)
741 	{
742 		nc_advise("ncvarput", status, "ncid %d", ncid);
743 		return -1;
744 	}
745 	}
746 	return 0;
747 }
748 
749 
750 int
ncvarget(int ncid,int varid,const long * start,const long * count,void * value)751 ncvarget(
752     int		ncid,
753     int		varid,
754     const long*	start,
755     const long*	count,
756     void*	value
757 )
758 {
759 	NDIMS_DECL
760 	A_DECL(stp, size_t, ndims, start);
761 	A_DECL(cntp, size_t, ndims, count);
762 	A_INIT(stp, size_t, ndims, start);
763 	A_INIT(cntp, size_t, ndims, count);
764 	{
765 	const int status = nc_get_vara(ncid, varid, stp, cntp, value);
766 	A_FREE(cntp);
767 	A_FREE(stp);
768 	if(status != NC_NOERR)
769 	{
770 		nc_advise("ncvarget", status, "ncid %d; varid %d", ncid, varid);
771 		return -1;
772 	}
773 	}
774 	return 0;
775 }
776 
777 
778 int
ncvarputs(int ncid,int varid,const long * start,const long * count,const long * stride,const void * value)779 ncvarputs(
780     int		ncid,
781     int		varid,
782     const long*	start,
783     const long*	count,
784     const long*	stride,
785     const void*	value
786 )
787 {
788 	if(stride == NULL)
789 		return ncvarput(ncid, varid, start, count, value);
790 	/* else */
791 	{
792 	NDIMS_DECL
793 	A_DECL(stp, size_t, ndims, start);
794 	A_DECL(cntp, size_t, ndims, count);
795 	A_DECL(strdp, ptrdiff_t, ndims, stride);
796 	A_INIT(stp, size_t, ndims, start);
797 	A_INIT(cntp, size_t, ndims, count);
798 	A_INIT(strdp, ptrdiff_t, ndims, stride);
799 	{
800 	const int status = nc_put_vars(ncid, varid, stp, cntp, strdp, value);
801 	A_FREE(strdp);
802 	A_FREE(cntp);
803 	A_FREE(stp);
804 	if(status != NC_NOERR)
805 	{
806 		nc_advise("ncvarputs", status, "ncid %d", ncid);
807 		return -1;
808 	}
809 	}
810 	return 0;
811 	}
812 }
813 
814 
815 int
ncvargets(int ncid,int varid,const long * start,const long * count,const long * stride,void * value)816 ncvargets(
817     int		ncid,
818     int		varid,
819     const long*	start,
820     const long*	count,
821     const long*	stride,
822     void*	value
823 )
824 {
825 	if(stride == NULL)
826 		return ncvarget(ncid, varid, start, count, value);
827 	/* else */
828 	{
829 	NDIMS_DECL
830 	A_DECL(stp, size_t, ndims, start);
831 	A_DECL(cntp, size_t, ndims, count);
832 	A_DECL(strdp, ptrdiff_t, ndims, stride);
833 	A_INIT(stp, size_t, ndims, start);
834 	A_INIT(cntp, size_t, ndims, count);
835 	A_INIT(strdp, ptrdiff_t, ndims, stride);
836 	{
837 	const int status = nc_get_vars(ncid, varid, stp, cntp, strdp, value);
838 	A_FREE(strdp);
839 	A_FREE(cntp);
840 	A_FREE(stp);
841 	if(status != NC_NOERR)
842 	{
843 		nc_advise("ncvargets", status, "ncid %d", ncid);
844 		return -1;
845 	}
846 	}
847 	return 0;
848 	}
849 }
850 
851 
852 int
ncvarputg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,const void * value)853 ncvarputg(
854     int		ncid,
855     int		varid,
856     const long*	start,
857     const long*	count,
858     const long*	stride,
859     const long*	map,
860     const void* value
861 )
862 {
863 	if(map == NULL)
864 		return ncvarputs(ncid, varid, start, count, stride, value);
865 	/* else */
866 	{
867 	NDIMS_DECL
868 	A_DECL(stp, size_t, ndims, start);
869 	A_DECL(cntp, size_t, ndims, count);
870 	A_DECL(strdp, ptrdiff_t, ndims, stride);
871 	A_DECL(imp, ptrdiff_t, ndims, map);
872 	A_INIT(stp, size_t, ndims, start);
873 	A_INIT(cntp, size_t, ndims, count);
874 	A_INIT(strdp, ptrdiff_t, ndims, stride);
875 	A_INIT(imp, ptrdiff_t, ndims, map);
876 	{
877 	const int status = nc_put_varm(ncid, varid,
878 			 stp, cntp, strdp, imp, value);
879 	A_FREE(imp);
880 	A_FREE(strdp);
881 	A_FREE(cntp);
882 	A_FREE(stp);
883 	if(status != NC_NOERR)
884 	{
885 		nc_advise("ncvarputg", status, "ncid %d", ncid);
886 		return -1;
887 	}
888 	}
889 	return 0;
890 	}
891 }
892 
893 
894 int
ncvargetg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,void * value)895 ncvargetg(
896     int		ncid,
897     int		varid,
898     const long*	start,
899     const long*	count,
900     const long*	stride,
901     const long*	map,
902     void*	value
903 )
904 {
905 	if(map == NULL)
906 		return ncvargets(ncid, varid, start, count, stride, value);
907 	/* else */
908 	{
909 	NDIMS_DECL
910 	A_DECL(stp, size_t, ndims, start);
911 	A_DECL(cntp, size_t, ndims, count);
912 	A_DECL(strdp, ptrdiff_t, ndims, stride);
913 	A_DECL(imp, ptrdiff_t, ndims, map);
914 	A_INIT(stp, size_t, ndims, start);
915 	A_INIT(cntp, size_t, ndims, count);
916 	A_INIT(strdp, ptrdiff_t, ndims, stride);
917 	A_INIT(imp, ptrdiff_t, ndims, map);
918 	{
919 	const int status = nc_get_varm(ncid, varid,
920 			stp, cntp, strdp, imp, value);
921 	A_FREE(imp);
922 	A_FREE(strdp);
923 	A_FREE(cntp);
924 	A_FREE(stp);
925 	if(status != NC_NOERR)
926 	{
927 		nc_advise("ncvargetg", status, "ncid %d", ncid);
928 		return -1;
929 	}
930 	}
931 	return 0;
932 	}
933 }
934 
935 
936 int
ncvarrename(int ncid,int varid,const char * name)937 ncvarrename(
938     int		ncid,
939     int		varid,
940     const char*	name
941 )
942 {
943 	const int status = nc_rename_var(ncid, varid, name);
944 	if(status != NC_NOERR)
945 	{
946 		nc_advise("ncvarrename", status, "ncid %d", ncid);
947 		return -1;
948 	}
949 	return varid;
950 }
951 
952 
953 int
ncattput(int ncid,int varid,const char * name,nc_type datatype,int len,const void * value)954 ncattput(
955     int		ncid,
956     int		varid,
957     const char*	name,
958     nc_type	datatype,
959     int		len,
960     const void*	value
961 )
962 {
963 	const int status = nc_put_att(ncid, varid, name, datatype, len, value);
964 	if(status != NC_NOERR)
965 	{
966 		nc_advise("ncattput", status, "ncid %d", ncid);
967 		return -1;
968 	}
969 	return 0;
970 }
971 
972 
973 int
ncattinq(int ncid,int varid,const char * name,nc_type * datatype,int * len)974 ncattinq(
975     int		ncid,
976     int		varid,
977     const char*	name,
978     nc_type*	datatype,
979     int*	len
980 )
981 {
982 	size_t ll;
983 	const int status = nc_inq_att(ncid, varid, name, datatype, &ll);
984 	if(status != NC_NOERR)
985 	{
986 		nc_advise("ncattinq", status,
987 		    "ncid %d; varid %d; attname \"%s\"",
988 		    ncid, varid, name);
989 		return -1;
990 	}
991 
992 	if(len != NULL)
993 		*len = (int) ll;
994 
995 	return 1;
996 
997 }
998 
999 
1000 int
ncattget(int ncid,int varid,const char * name,void * value)1001 ncattget(
1002     int		ncid,
1003     int		varid,
1004     const char*	name,
1005     void*	value
1006 )
1007 {
1008 	const int status = nc_get_att(ncid, varid, name, value);
1009 	if(status != NC_NOERR)
1010 	{
1011 		nc_advise("ncattget", status, "ncid %d", ncid);
1012 		return -1;
1013 	}
1014 	return 1;
1015 }
1016 
1017 
1018 int
ncattcopy(int ncid_in,int varid_in,const char * name,int ncid_out,int varid_out)1019 ncattcopy(
1020     int		ncid_in,
1021     int		varid_in,
1022     const char*	name,
1023     int		ncid_out,
1024     int		varid_out
1025 )
1026 {
1027 	const int status = nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out);
1028 	if(status != NC_NOERR)
1029 	{
1030 		nc_advise("ncattcopy", status, "%s", name);
1031 		return -1;
1032 	}
1033 	return 0;
1034 }
1035 
1036 
1037 int
ncattname(int ncid,int varid,int attnum,char * name)1038 ncattname(
1039     int		ncid,
1040     int		varid,
1041     int		attnum,
1042     char*	name
1043 )
1044 {
1045 	const int status = nc_inq_attname(ncid, varid, attnum, name);
1046 	if(status != NC_NOERR)
1047 	{
1048 		nc_advise("ncattname", status, "ncid %d", ncid);
1049 		return -1;
1050 	}
1051 	return attnum;
1052 }
1053 
1054 
1055 int
ncattrename(int ncid,int varid,const char * name,const char * newname)1056 ncattrename(
1057     int		ncid,
1058     int		varid,
1059     const char*	name,
1060     const char*	newname
1061 )
1062 {
1063 	const int status = nc_rename_att(ncid, varid, name, newname);
1064 	if(status != NC_NOERR)
1065 	{
1066 		nc_advise("ncattrename", status, "ncid %d", ncid);
1067 		return -1;
1068 	}
1069 	return 1;
1070 }
1071 
1072 
1073 int
ncattdel(int ncid,int varid,const char * name)1074 ncattdel(
1075     int		ncid,
1076     int		varid,
1077     const char*	name
1078 )
1079 {
1080 	 const int status = nc_del_att(ncid, varid, name);
1081 	if(status != NC_NOERR)
1082 	{
1083 		nc_advise("ncattdel", status, "ncid %d", ncid);
1084 		return -1;
1085 	}
1086 	return 1;
1087 }
1088 
1089 #endif /* NO_NETCDF_2 */
1090 
1091 #ifndef NO_NETCDF_2
1092 
1093 int
ncsetfill(int ncid,int fillmode)1094 ncsetfill(
1095     int		ncid,
1096     int		fillmode
1097 )
1098 {
1099 	int oldmode = -1;
1100 	const int status = nc_set_fill(ncid, fillmode, &oldmode);
1101 	if(status != NC_NOERR)
1102 	{
1103 		nc_advise("ncsetfill", status, "ncid %d", ncid);
1104 		return -1;
1105 	}
1106 	return oldmode;
1107 }
1108 
1109 
1110 int
ncrecinq(int ncid,int * nrecvars,int * recvarids,long * recsizes)1111 ncrecinq(
1112     int		ncid,
1113     int*	nrecvars,
1114     int*	recvarids,
1115     long*	recsizes
1116 )
1117 {
1118 	size_t nrv = 0;
1119 	size_t rs[NC_MAX_VARS]; /* TODO */
1120 	const int status = nc_inq_rec(ncid, &nrv, recvarids, rs);
1121 	if(status != NC_NOERR)
1122 	{
1123 		nc_advise("ncrecinq", status, "ncid %d", ncid);
1124 		return -1;
1125 	}
1126 
1127 	if(nrecvars != NULL)
1128 		*nrecvars = (int) nrv;
1129 
1130 	if(recsizes != NULL)
1131 	{
1132 		size_t ii;
1133 		for(ii = 0; ii < nrv; ii++)
1134 		{
1135 			recsizes[ii] = (long) rs[ii];
1136 		}
1137 	}
1138 
1139 	return (int) nrv;
1140 }
1141 
1142 
1143 int
ncrecget(int ncid,long recnum,void ** datap)1144 ncrecget(
1145     int		ncid,
1146     long	recnum,
1147     void**	datap
1148 )
1149 {
1150 	const int status = nc_get_rec(ncid, (size_t)recnum, datap);
1151 	if(status != NC_NOERR)
1152 	{
1153 		nc_advise("ncrecget", status, "ncid %d", ncid);
1154 		return -1;
1155 	}
1156 	return 0;
1157 }
1158 
1159 
1160 int
ncrecput(int ncid,long recnum,void * const * datap)1161 ncrecput(
1162     int		ncid,
1163     long	recnum,
1164     void* const* datap
1165 )
1166 {
1167 	const int status = nc_put_rec(ncid, (size_t)recnum, datap);
1168 	if(status != NC_NOERR)
1169 	{
1170 		nc_advise("ncrecput", status, "ncid %d", ncid);
1171 		return -1;
1172 	}
1173 	return 0;
1174 }
1175 
1176 #endif /* NO_NETCDF_2 */
1177