Coverage Report

Created: 2023-05-28 06:42

/src/netcdf-c/libnczarr/zinternal.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2003-2018, University Corporation for Atmospheric
2
 * Research. See the COPYRIGHT file for copying and redistribution
3
 * conditions.
4
 */
5
6
/**
7
 * @file @internal Internal netcdf-4 functions.
8
 *
9
 * This file contains functions internal to the netcdf4 library. None of
10
 * the functions in this file are exposed in the exetnal API. These
11
 * functions all relate to the manipulation of netcdf-4's in-memory
12
 * buffer of metadata information, i.e. the linked list of NC
13
 * structs.
14
 *
15
 * @author Dennis Heimbigner, Ed Hartnett
16
 */
17
18
#include "zincludes.h"
19
#include "zfilter.h"
20
21
/* Forward */
22
23
#ifdef LOGGING
24
/* This is the severity level of messages which will be logged. Use
25
   severity 0 for errors, 1 for important log messages, 2 for less
26
   important, etc. */
27
extern int nc_log_level;
28
#endif /* LOGGING */
29
30
#ifdef LOOK
31
/**
32
 * @internal Provide a wrapper for H5Eset_auto
33
 * @param func Pointer to func.
34
 * @param client_data Client data.
35
 *
36
 * @return 0 for success
37
 */
38
static herr_t
39
set_auto(void* func, void *client_data)
40
{
41
#ifdef DEBUGH5
42
    return H5Eset_auto2(H5E_DEFAULT,(H5E_auto2_t)h5catch,client_data);
43
#else
44
    return H5Eset_auto2(H5E_DEFAULT,(H5E_auto2_t)func,client_data);
45
#endif
46
}
47
#endif
48
49
/**
50
 * @internal Provide a function to do any necessary initialization of
51
 * the ZARR library.
52
 */
53
int
54
NCZ_initialize_internal(void)
55
1
{
56
1
    int stat = NC_NOERR;
57
1
    char* dimsep = NULL;
58
1
    NCglobalstate* ngs = NULL;
59
60
1
    ncz_initialized = 1;
61
1
    ngs = NC_getglobalstate();
62
1
    if(ngs != NULL) {
63
        /* Defaults */
64
1
  ngs->zarr.dimension_separator = DFALT_DIM_SEPARATOR;
65
1
        dimsep = NC_rclookup("ZARR.DIMENSION_SEPARATOR",NULL,NULL);
66
1
        if(dimsep != NULL) {
67
            /* Verify its value */
68
0
      if(dimsep != NULL && strlen(dimsep) == 1 && islegaldimsep(dimsep[0]))
69
0
    ngs->zarr.dimension_separator = dimsep[0];
70
0
        }    
71
1
    }
72
73
1
    return stat;
74
1
}
75
76
/**
77
 * @internal Provide a function to do any necessary finalization of
78
 * the ZARR library.
79
 */
80
int
81
NCZ_finalize_internal(void)
82
1
{
83
    /* Reclaim global resources */
84
1
    ncz_initialized = 0;
85
1
#ifdef ENABLE_NCZARR_FILTERS
86
1
    NCZ_filter_finalize();
87
1
#endif
88
#ifdef ENABLE_S3
89
    NCZ_s3finalize();
90
#endif
91
1
    return NC_NOERR;
92
1
}
93
94
/**
95
 * @internal Given a varid, return the maximum length of a dimension
96
 * using dimid.
97
 *
98
 * @param grp Pointer to group info struct.
99
 * @param varid Variable ID.
100
 * @param dimid Dimension ID.
101
 * @param maxlen Pointer that gets the max length.
102
 *
103
 * @return ::NC_NOERR No error.
104
 * @author Dennis Heimbigner, Ed Hartnett
105
 */
106
static int
107
find_var_dim_max_length(NC_GRP_INFO_T *grp, int varid, int dimid,
108
                        size_t *maxlen)
109
0
{
110
0
    NC_VAR_INFO_T *var;
111
0
    int retval = NC_NOERR;
112
113
0
    *maxlen = 0;
114
115
    /* Find this var. */
116
0
    var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
117
0
    if (!var) return NC_ENOTVAR;
118
0
    assert(var->hdr.id == varid);
119
120
    /* If the var hasn't been created yet, its size is 0. */
121
0
    if (!var->created)
122
0
    {
123
0
        *maxlen = 0;
124
0
    }
125
0
    else
126
0
    {
127
        /* Get the number of records in the dataset. */
128
#ifdef LOOK
129
#if 0
130
not needed        if ((retval = ncz_open_var_grp2(grp, var->hdr.id, &datasetid)))
131
            BAIL(retval);
132
#endif
133
        if ((spaceid = H5Dget_space(datasetid)) < 0)
134
            BAIL(NC_EHDFERR);
135
        /* If it's a scalar dataset, it has length one. */
136
        if (H5Sget_simple_extent_type(spaceid) == H5S_SCALAR)
137
        {
138
            *maxlen = (var->dimids && var->dimids[0] == dimid) ? 1 : 0;
139
        }
140
        else
141
        {
142
            /* Check to make sure ndims is right, then get the len of each
143
               dim in the space. */
144
            if ((dataset_ndims = H5Sget_simple_extent_ndims(spaceid)) < 0)
145
                BAIL(NC_EHDFERR);
146
            if (dataset_ndims != var->ndims)
147
                BAIL(NC_EHDFERR);
148
            if (!(h5dimlen = malloc(dataset_ndims * sizeof(hsize_t))))
149
                BAIL(NC_ENOMEM);
150
            if (!(h5dimlenmax = malloc(dataset_ndims * sizeof(hsize_t))))
151
                BAIL(NC_ENOMEM);
152
            if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid,
153
                                                           h5dimlen, h5dimlenmax)) < 0)
154
                BAIL(NC_EHDFERR);
155
            LOG((5, "find_var_dim_max_length: varid %d len %d max: %d",
156
                 varid, (int)h5dimlen[0], (int)h5dimlenmax[0]));
157
            for (d=0; d<dataset_ndims; d++) {
158
                if (var->dimids[d] == dimid) {
159
                    *maxlen = *maxlen > h5dimlen[d] ? *maxlen : h5dimlen[d];
160
                }
161
            }
162
        }
163
#endif /*LOOK*/
164
0
    }
165
166
#ifdef LOOK
167
exit:
168
    if (spaceid > 0 && H5Sclose(spaceid) < 0)
169
        BAIL2(NC_EHDFERR);
170
    if (h5dimlen) free(h5dimlen);
171
    if (h5dimlenmax) free(h5dimlenmax);
172
#endif
173
0
    return retval;
174
0
}
175
176
#ifdef LOOK
177
/**
178
 * @internal Search for type with a given HDF type id.
179
 *
180
 * @param h5 File
181
 * @param target_hdf_typeid ZARR type ID to find.
182
 *
183
 * @return Pointer to type info struct, or NULL if not found.
184
 * @author Dennis Heimbigner, Ed Hartnett
185
 */
186
NC_TYPE_INFO_T *
187
ncz_rec_find_hdf_type(NC_FILE_INFO_T *h5, hid_t target_hdf_typeid)
188
{
189
    NC_TYPE_INFO_T *type;
190
    int i;
191
192
    assert(h5);
193
194
    for (i = 0; i < nclistlength(h5->alltypes); i++)
195
    {
196
        type = (NC_TYPE_INFO_T*)nclistget(h5->alltypes, i);
197
        if(type == NULL) continue;
198
199
#ifdef LOOK
200
        /* Select the ZARR typeid to use. */
201
        hdf_typeid = ncz_type->native_hdf_typeid ?
202
            ncz_type->native_hdf_typeid : ncz_type->hdf_typeid;
203
204
        /* Is this the type we are searching for? */
205
        if ((equal = H5Tequal(hdf_typeid, target_hdf_typeid)) < 0)
206
            return NULL;
207
        if (equal)
208
            return type;
209
#endif
210
    }
211
    /* Can't find it. Fate, why do you mock me? */
212
    return NULL;
213
}
214
#endif
215
216
/**
217
 * @internal Find the actual length of a dim by checking the length of
218
 * that dim in all variables that use it, in grp or children. **len
219
 * must be initialized to zero before this function is called.
220
 *
221
 * @param grp Pointer to group info struct.
222
 * @param dimid Dimension ID.
223
 * @param len Pointer to pointer that gets length.
224
 *
225
 * @return ::NC_NOERR No error.
226
 * @author Dennis Heimbigner, Ed Hartnett
227
 */
228
int
229
ncz_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len)
230
0
{
231
0
    NC_VAR_INFO_T *var;
232
0
    int retval;
233
0
    int i;
234
235
0
    assert(grp && len);
236
0
    LOG((3, "%s: grp->name %s dimid %d", __func__, grp->hdr.name, dimid));
237
238
    /* If there are any groups, call this function recursively on
239
     * them. */
240
0
    for (i = 0; i < ncindexsize(grp->children); i++) {
241
0
        if ((retval = ncz_find_dim_len((NC_GRP_INFO_T*)ncindexith(grp->children, i),
242
0
                                       dimid, len)))
243
0
            return retval;
244
0
    }
245
    /* For all variables in this group, find the ones that use this
246
     * dimension, and remember the max length. */
247
0
    for (i = 0; i < ncindexsize(grp->vars); i++)
248
0
    {
249
0
        size_t mylen;
250
0
        var = (NC_VAR_INFO_T *)ncindexith(grp->vars, i);
251
0
        assert(var);
252
253
        /* Find max length of dim in this variable... */
254
0
        if ((retval = find_var_dim_max_length(grp, var->hdr.id, dimid, &mylen)))
255
0
            return retval;
256
257
0
        **len = **len > mylen ? **len : mylen;
258
0
    }
259
260
0
    return NC_NOERR;
261
0
}
262
263
#if 0
264
/**
265
 * @internal Close ZARR resources for global atts in a group.
266
 *
267
 * @param grp Pointer to group info struct.
268
 *
269
 * @return ::NC_NOERR No error.
270
 * @return ::NC_EHDFERR ZARR error.
271
 * @author Dennis Heimbigner, Ed Hartnett
272
 */
273
274
static int
275
close_gatts(NC_GRP_INFO_T *grp)
276
{
277
    NC_ATT_INFO_T *att;
278
    int a;
279
280
    for (a = 0; a < ncindexsize(grp->att); a++)
281
    {
282
        att = (NC_ATT_INFO_T *)ncindexith(grp->att, a);
283
        assert(att && att->format_att_info);
284
285
#ifdef LOOK
286
        /* Close the ZARR typeid. */
287
        if (ncz_att->native_hdf_typeid &&
288
            H5Tclose(ncz_att->native_hdf_typeid) < 0)
289
            return NC_EHDFERR;
290
#endif
291
    }
292
    return NC_NOERR;
293
}
294
#endif /*0*/
295
296
#if 0
297
/**
298
 * @internal Close ZARR resources for vars in a group.
299
 *
300
 * @param grp Pointer to group info struct.
301
 *
302
 * @return ::NC_NOERR No error.
303
 * @return ::NC_EHDFERR ZARR error.
304
 * @author Dennis Heimbigner, Ed Hartnett
305
 */
306
static int
307
close_vars(NC_GRP_INFO_T *grp)
308
{
309
    NC_VAR_INFO_T *var;
310
    NC_ATT_INFO_T *att;
311
    int a, i;
312
313
    for (i = 0; i < ncindexsize(grp->vars); i++)
314
    {
315
        var = (NC_VAR_INFO_T *)ncindexith(grp->vars, i);
316
        assert(var && var->format_var_info);
317
318
        /* Close the ZARR dataset associated with this var. */
319
#ifdef LOOK
320
        if (ncz_var->hdf_datasetid)
321
#endif
322
        {
323
#ifdef LOOK
324
            LOG((3, "closing ZARR dataset %lld", ncz_var->hdf_datasetid));
325
            if (H5Dclose(ncz_var->hdf_datasetid) < 0)
326
                return NC_EHDFERR;
327
#endif
328
            if (var->fill_value)
329
            {
330
                if (var->type_info)
331
                {
332
        int stat = NC_NOERR;
333
        if((stat = nc_reclaim_data(grp->nc4_info->controller->ext_ncid,var->type_info->hdr.id,var->fill_value,1)))
334
            return stat;
335
        nullfree(var->fill_value);
336
                }
337
            }
338
        }
339
340
#ifdef LOOK
341
        /* Delete any ZARR dimscale objid information. */
342
        if (ncz_var->dimscale_ncz_objids)
343
            free(ncz_var->dimscale_ncz_objids);
344
#endif
345
346
        for (a = 0; a < ncindexsize(var->att); a++)
347
        {
348
            att = (NC_ATT_INFO_T *)ncindexith(var->att, a);
349
            assert(att && att->format_att_info);
350
351
#ifdef LOOK
352
            /* Close the ZARR typeid if one is open. */
353
            if (ncz_att->native_hdf_typeid &&
354
                H5Tclose(ncz_att->native_hdf_typeid) < 0)
355
                return NC_EHDFERR;
356
#endif
357
        }
358
359
  /* Reclaim filters */
360
  if(var->filters != NULL) {
361
      (void)NCZ_filter_freelists(var);
362
  }
363
  var->filters = NULL;
364
365
    }
366
367
    return NC_NOERR;
368
}
369
#endif /*0*/
370
371
#if 0
372
/**
373
 * @internal Close ZARR resources for dims in a group.
374
 *
375
 * @param grp Pointer to group info struct.
376
 *
377
 * @return ::NC_NOERR No error.
378
 * @return ::NC_EHDFERR ZARR error.
379
 * @author Dennis Heimbigner, Ed Hartnett
380
 */
381
static int
382
close_dims(NC_GRP_INFO_T *grp)
383
{
384
    NC_DIM_INFO_T *dim;
385
    int i;
386
387
    for (i = 0; i < ncindexsize(grp->dim); i++)
388
    {
389
        dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
390
        assert(dim && dim->format_dim_info);
391
392
#ifdef LOOK
393
        /* If this is a dim without a coordinate variable, then close
394
         * the ZARR DIM_WITHOUT_VARIABLE dataset associated with this
395
         * dim. */
396
        if (ncz_dim->hdf_dimscaleid && H5Dclose(ncz_dim->hdf_dimscaleid) < 0)
397
            return NC_EHDFERR;
398
#endif
399
    }
400
401
    return NC_NOERR;
402
}
403
#endif /*0*/
404
405
#if 0
406
/**
407
 * @internal Close ZARR resources for types in a group.  Set values to
408
 * 0 after closing types. Because of type reference counters, these
409
 * closes can be called multiple times.
410
 *
411
 * @param grp Pointer to group info struct.
412
 *
413
 * @return ::NC_NOERR No error.
414
 * @return ::NC_EHDFERR ZARR error.
415
 * @author Dennis Heimbigner, Ed Hartnett
416
 */
417
static int
418
close_types(NC_GRP_INFO_T *grp)
419
{
420
    int i;
421
422
    for (i = 0; i < ncindexsize(grp->type); i++)
423
    {
424
        NC_TYPE_INFO_T *type;
425
426
        type = (NC_TYPE_INFO_T *)ncindexith(grp->type, i);
427
        assert(type && type->format_type_info);
428
429
#ifdef LOOK
430
        /* Close any open user-defined ZARR typeids. */
431
        if (ncz_type->hdf_typeid && H5Tclose(ncz_type->hdf_typeid) < 0)
432
            return NC_EHDFERR;
433
        ncz_type->hdf_typeid = 0;
434
        if (ncz_type->native_hdf_typeid &&
435
            H5Tclose(ncz_type->native_hdf_typeid) < 0)
436
            return NC_EHDFERR;
437
        ncz_type->native_hdf_typeid = 0;
438
#endif
439
    }
440
441
    return NC_NOERR;
442
}
443
#endif /*0*/
444
445
#if 0
446
/**
447
 * @internal Recursively free ZARR objects for a group (and everything
448
 * it contains).
449
 *
450
 * @param grp Pointer to group info struct.
451
 *
452
 * @return ::NC_NOERR No error.
453
 * @return ::NC_EHDFERR ZARR error.
454
 * @author Dennis Heimbigner, Ed Hartnett
455
 */
456
static int
457
ncz_rec_grp_NCZ_del(NC_GRP_INFO_T *grp)
458
{
459
    int i;
460
    int retval;
461
462
    assert(grp && grp->format_grp_info);
463
    LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
464
465
    /* Recursively call this function for each child, if any, stopping
466
     * if there is an error. */
467
    for (i = 0; i < ncindexsize(grp->children); i++)
468
        if ((retval = ncz_rec_grp_NCZ_del((NC_GRP_INFO_T *)ncindexith(grp->children,
469
                                                                       i))))
470
            return retval;
471
472
    /* Close ZARR resources associated with global attributes. */
473
    if ((retval = close_gatts(grp)))
474
        return retval;
475
476
    /* Close ZARR resources associated with vars. */
477
    if ((retval = close_vars(grp)))
478
        return retval;
479
480
    /* Close ZARR resources associated with dims. */
481
    if ((retval = close_dims(grp)))
482
        return retval;
483
484
    /* Close ZARR resources associated with types. */
485
    if ((retval = close_types(grp)))
486
        return retval;
487
488
    /* Close the ZARR group. */
489
    LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
490
#ifdef LOOK
491
    if (ncz_grp->hdf_grpid && H5Gclose(ncz_grp->hdf_grpid) < 0)
492
        return NC_EHDFERR;
493
#endif
494
495
    return NC_NOERR;
496
}
497
#endif /*0*/
498
499
/**
500
 * @internal Given an ncid and varid, get pointers to the group and var
501
 * metadata. Lazy var metadata reads are done as needed.
502
 *
503
 * @param ncid File ID.
504
 * @param varid Variable ID.
505
 * @param h5 Pointer that gets pointer to the NC_FILE_INFO_T struct
506
 * for this file. Ignored if NULL.
507
 * @param grp Pointer that gets pointer to group info. Ignored if
508
 * NULL.
509
 * @param var Pointer that gets pointer to var info. Ignored if NULL.
510
 *
511
 * @return ::NC_NOERR No error.
512
 * @return ::NC_ENOTVAR Variable not found.
513
 * @author Dennis Heimbigner, Ed Hartnett
514
 */
515
int
516
ncz_find_grp_file_var(int ncid, int varid, NC_FILE_INFO_T **h5,
517
                         NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var)
518
0
{
519
0
    NC_FILE_INFO_T *my_h5;
520
0
    NC_VAR_INFO_T *my_var;
521
0
    int retval;
522
523
    /* Delegate to libsrc4 */
524
0
    if((retval = nc4_find_grp_h5_var(ncid,varid,&my_h5,grp,&my_var))) return retval;
525
526
    /* Do we need to read var metadata? */
527
0
    if (!my_var->meta_read && my_var->created)
528
0
        if ((retval = ncz_get_var_meta(my_h5, my_var)))
529
0
            return retval;
530
0
    if (var) *var = my_var;
531
0
    if (h5) *h5 = my_h5;
532
0
    return NC_NOERR;
533
0
}
534
535
/**
536
 * @internal Given an ncid, varid, and attribute name, return
537
 * normalized name and (optionally) pointers to the file, group,
538
 * var, and att info structs.
539
 * Lazy reads of attributes and variable metadata are done as needed.
540
 *
541
 * @param ncid File/group ID.
542
 * @param varid Variable ID.
543
 * @param name Name to of attribute.
544
 * @param attnum Number of attribute.
545
 * @param use_name If true, use the name to get the
546
 * attribute. Otherwise use the attnum.
547
 * @param norm_name Pointer to storage of size NC_MAX_NAME + 1,
548
 * which will get the normalized name, if use_name is true. Ignored if
549
 * NULL.
550
 * @param h5 Pointer to pointer that gets file info struct. Ignored if
551
 * NULL.
552
 * @param grp Pointer to pointer that gets group info struct. Ignored
553
 * if NULL.
554
 * @param h5 Pointer to pointer that gets variable info
555
 * struct. Ignored if NULL.
556
 * @param att Pointer to pointer that gets attribute info
557
 * struct. Ignored if NULL.
558
 *
559
 * @return ::NC_NOERR No error.
560
 * @return ::NC_EBADID Bad ncid.
561
 * @return ::NC_ENOTVAR Variable not found.
562
 * @return ::NC_ENOTATT Attribute not found.
563
 * @author Dennis Heimbigner, Ed Hartnett
564
 */
565
int
566
ncz_find_grp_var_att(int ncid, int varid, const char *name, int attnum,
567
                          int use_name, char *norm_name, NC_FILE_INFO_T **h5,
568
                          NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var,
569
                          NC_ATT_INFO_T **att)
570
0
{
571
0
    NC_FILE_INFO_T *my_h5;
572
0
    NC_GRP_INFO_T *my_grp;
573
0
    NC_VAR_INFO_T *my_var = NULL;
574
0
    NC_ATT_INFO_T *my_att;
575
0
    char my_norm_name[NC_MAX_NAME + 1] = "";
576
0
    NCindex *attlist = NULL;
577
0
    int retval;
578
579
0
    LOG((4, "%s: ncid %d varid %d attnum %d use_name %d", __func__, ncid, varid,
580
0
         attnum, use_name));
581
582
    /* Don't need to provide name unless getting att pointer and using
583
     * use_name. */
584
0
    assert(!att || ((use_name && name) || !use_name));
585
586
    /* Find info for this file, group, and h5 info. */
587
0
    if ((retval = nc4_find_nc_grp_h5(ncid, NULL, &my_grp, &my_h5)))
588
0
        return retval;
589
0
    assert(my_grp && my_h5);
590
591
    /* Read the attributes for this var, if any */
592
0
    switch (retval = ncz_getattlist(my_grp, varid, &my_var, &attlist)) {
593
0
    case NC_NOERR: assert(attlist); break;
594
0
    case NC_EEMPTY: retval = NC_NOERR; attlist = NULL; break; /* variable has no attributes */
595
0
    default: return retval; /* significant error */
596
0
    }
597
598
    /* Need a name if use_name is true. */
599
0
    if (use_name && !name)
600
0
        return NC_EBADNAME;
601
602
    /* Normalize the name. */
603
0
    if (use_name)
604
0
        if ((retval = nc4_normalize_name(name, my_norm_name)))
605
0
            return retval;
606
607
    /* Now find the attribute by name or number. */
608
0
    if (att)
609
0
    {
610
0
        my_att = use_name ? (NC_ATT_INFO_T *)ncindexlookup(attlist, my_norm_name) :
611
0
            (NC_ATT_INFO_T *)ncindexith(attlist, attnum);
612
0
        if (!my_att)
613
0
            return NC_ENOTATT;
614
0
    }
615
616
    /* Give the people what they want. */
617
0
    if (norm_name)
618
0
        strncpy(norm_name, my_norm_name, NC_MAX_NAME);
619
0
    if (h5)
620
0
        *h5 = my_h5;
621
0
    if (grp)
622
0
        *grp = my_grp;
623
0
    if (var)
624
0
        *var = my_var;
625
0
    if (att)
626
0
        *att = my_att;
627
628
0
    return retval;
629
0
}
630
631
/**
632
 * @internal Ensure that either var->no_fill || var->fill_value != NULL.
633
 * Side effects: set as default if necessary and build _FillValue attribute.
634
 *
635
 * @param h5 Pointer to file info struct.
636
 * @param var Pointer to variable info struct.
637
 *
638
 * @returns NC_NOERR No error.
639
 * @returns NC_ENOMEM Out of memory.
640
 * @author Ed Hartnett, Dennis Heimbigner
641
 */
642
int
643
NCZ_ensure_fill_value(NC_VAR_INFO_T *var)
644
0
{
645
0
    size_t size;
646
0
    int retval = NC_NOERR;
647
0
    NC_FILE_INFO_T *h5 = var->container->nc4_info;
648
649
0
    if(var->no_fill)
650
0
        return NC_NOERR;
651
652
#if 0 /*LOOK*/
653
    /* Find out how much space we need for this type's fill value. */
654
    if (var->type_info->nc_type_class == NC_VLEN)
655
        size = sizeof(nc_vlen_t);
656
    else if (var->type_info->nc_type_class == NC_STRING)
657
        size = sizeof(char *);
658
    else
659
#endif
660
661
0
    if ((retval = nc4_get_typelen_mem(h5, var->type_info->hdr.id, &size))) goto done;
662
0
    assert(size);
663
664
    /* If the user has set a fill_value for this var, use, otherwise find the default fill value. */
665
666
0
    if (var->fill_value == NULL) {
667
  /* initialize the fill_value to the default */
668
  /* Allocate the fill_value space. */
669
0
        if((var->fill_value = calloc(1, size))==NULL)
670
0
      {retval = NC_ENOMEM; goto done;}
671
0
        if((retval = nc4_get_default_fill_value(var->type_info, var->fill_value))) {
672
            /* Note: release memory, but don't return error on failure */
673
0
      (void)NCZ_reclaim_fill_value(var);
674
0
      retval = NC_NOERR;
675
0
      goto done;
676
0
        }
677
0
    }
678
0
    assert(var->fill_value != NULL);
679
680
0
    LOG((4, "Found a fill value for var %s", var->hdr.name));
681
#if 0 /*LOOK*/
682
  /* Need to copy both vlen and a single basetype */
683
        if (var->type_info->nc_type_class == NC_VLEN)
684
        {
685
            nc_vlen_t *in_vlen = (nc_vlen_t *)(var->fill_value);
686
      nc_vlen-t *fv_vlen = (nc_vlen_t *)fill;
687
            size_t basetypesize = 0;
688
689
            if((retval=nc4_get_typelen_mem(h5, var->type_info->u.v.base_nc_typeid, &basetypesize)))
690
                return retval;
691
692
            fv_vlen->len = in_vlen->len;
693
            if (!(fv_vlen->p = malloc(basetypesize * in_vlen->len)))
694
            {
695
                free(*fillp);
696
                *fillp = NULL;
697
                return NC_ENOMEM;
698
            }
699
            memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * basetypesize);
700
        }
701
        else if (var->type_info->nc_type_class == NC_STRING)
702
        {
703
            if (*(char **)var->fill_value)
704
                if (!(**(char ***)fillp = strdup(*(char **)var->fill_value)))
705
                {
706
                    free(*fillp);
707
                    *fillp = NULL;
708
                    return NC_ENOMEM;
709
                }
710
        }
711
#endif /*0*/
712
0
done:
713
0
    return retval;
714
0
}
715
716
#ifdef LOGGING
717
/* We will need to check against nc log level from nc4internal.c. */
718
extern int nc_log_level;
719
720
/**
721
 * @internal This is like nc_set_log_level(), but will also turn on
722
 * ZARR internal logging, in addition to netCDF logging. This should
723
 * never be called by the user. It is called in open/create when the
724
 * nc logging level has changed.
725
 *
726
 * @return ::NC_NOERR No error.
727
 * @author Dennis Heimbigner, Ed Hartnett
728
 */
729
int
730
NCZ_set_log_level()
731
{
732
    /* If the user wants to completely turn off logging, turn off NCZ
733
       logging too. Now I truely can't think of what to do if this
734
       fails, so just ignore the return code. */
735
    if (nc_log_level == NC_TURN_OFF_LOGGING)
736
    {
737
#ifdef LOOK
738
        set_auto(NULL, NULL);
739
#endif
740
        LOG((1, "NCZ error messages turned off!"));
741
    }
742
    else
743
    {
744
#ifdef LOOK
745
        if (set_auto((H5E_auto_t)&H5Eprint1, stderr) < 0)
746
            LOG((0, "H5Eset_auto failed!"));
747
#endif
748
        LOG((1, "NCZ error messages turned on."));
749
    }
750
751
    return NC_NOERR;
752
}
753
#endif /* LOGGING */
754
755
/**
756
 * @internal Get the format (i.e. NC_FORMAT_NETCDF4 pr
757
 * NC_FORMAT_NETCDF4_CLASSIC) of an open netCDF-4 file.
758
 *
759
 * @param ncid File ID (ignored).
760
 * @param formatp Pointer that gets the constant indicating format.
761
762
 * @return ::NC_NOERR No error.
763
 * @return ::NC_EBADID Bad ncid.
764
 * @author Ed Hartnett
765
 */
766
int
767
NCZ_inq_format(int ncid, int *formatp)
768
0
{
769
0
    int stat = NC_NOERR;
770
771
0
    ZTRACE(0,"ncid=%d formatp=%p",ncid,formatp);
772
0
    stat = NC4_inq_format(ncid,formatp);
773
0
    return ZUNTRACEX(stat,"formatp=%d",(formatp?-1:*formatp));
774
0
}
775
776
/**
777
 * @internal Return the extended format (i.e. the dispatch model),
778
 * plus the mode associated with an open file.
779
 *
780
 * @param ncid File ID (ignored).
781
 * @param formatp a pointer that gets the extended format. Note that
782
 * this is not the same as the format provided by nc_inq_format(). The
783
 * extended foramt indicates the dispatch layer model. NetCDF-4 files
784
 * will always get NC_FORMATX_NC4.
785
 * @param modep a pointer that gets the open/create mode associated with
786
 * this file. Ignored if NULL.
787
788
 * @return ::NC_NOERR No error.
789
 * @return ::NC_EBADID Bad ncid.
790
 * @author Dennis Heimbigner
791
 */
792
int
793
NCZ_inq_format_extended(int ncid, int *formatp, int *modep)
794
0
{
795
0
    NC *nc;
796
0
    int retval;
797
798
0
    LOG((2, "%s: ncid 0x%x", __func__, ncid));
799
800
0
    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, NULL, NULL)))
801
0
        return NC_EBADID;
802
803
0
    if(modep)
804
0
        *modep = nc->mode|NC_NETCDF4;
805
806
0
    if (formatp)
807
0
        *formatp = NC_FORMATX_NCZARR;
808
809
0
    return NC_NOERR;
810
0
}