Coverage Report

Created: 2025-10-28 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libnczarr/zarr.c
Line
Count
Source
1
/*********************************************************************
2
 *   Copyright 2018, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "zincludes.h"
7
#include <stddef.h>
8
9
/**************************************************/
10
/* Forwards */
11
12
static int applycontrols(NCZ_FILE_INFO_T* zinfo);
13
14
/***************************************************/
15
/* API */
16
17
/**
18
@internal Create the topmost dataset object and setup up
19
          NCZ_FILE_INFO_T state.
20
@param zinfo - [in] the internal state
21
@return NC_NOERR
22
@author Dennis Heimbigner
23
*/
24
25
int
26
ncz_create_dataset(NC_FILE_INFO_T* file, NC_GRP_INFO_T* root, NClist* controls)
27
0
{
28
0
    int stat = NC_NOERR;
29
0
    NCZ_FILE_INFO_T* zinfo = NULL;
30
0
    NCZ_GRP_INFO_T* zgrp = NULL;
31
0
    NCURI* uri = NULL;
32
0
    NC* nc = NULL;
33
0
    NCjson* json = NULL;
34
0
    char* key = NULL;
35
36
0
    ZTRACE(3,"file=%s root=%s controls=%s",file->hdr.name,root->hdr.name,(controls?nczprint_envv(controls):"null"));
37
38
0
    nc = (NC*)file->controller;
39
40
    /* Add struct to hold NCZ-specific file metadata. */
41
0
    if (!(zinfo = calloc(1, sizeof(NCZ_FILE_INFO_T))))
42
0
        {stat = NC_ENOMEM; goto done;}
43
0
    file->format_file_info = zinfo;
44
0
    zinfo->common.file = file;
45
46
    /* Add struct to hold NCZ-specific group info. */
47
0
    if (!(zgrp = calloc(1, sizeof(NCZ_GRP_INFO_T))))
48
0
        {stat = NC_ENOMEM; goto done;}
49
0
    root->format_grp_info = zgrp;
50
0
    zgrp->common.file = file;
51
52
    /* Fill in NCZ_FILE_INFO_T */
53
0
    zinfo->creating = 1;
54
0
    zinfo->common.file = file;
55
0
    zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
56
0
    if((zinfo->controllist=nclistclone(controls,1)) == NULL)
57
0
  {stat = NC_ENOMEM; goto done;}
58
59
    /* fill in some of the zinfo and zroot fields */
60
0
    zinfo->zarr.zarr_version = atoi(ZARRVERSION);
61
0
    sscanf(NCZARRVERSION,"%lu.%lu.%lu",
62
0
     &zinfo->zarr.nczarr_version.major,
63
0
     &zinfo->zarr.nczarr_version.minor,
64
0
     &zinfo->zarr.nczarr_version.release);
65
66
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
67
68
    /* Apply client controls */
69
0
    if((stat = applycontrols(zinfo))) goto done;
70
71
    /* Load auth info from rc file */
72
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
73
0
    if(uri) {
74
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
75
0
      goto done;
76
0
    }
77
78
    /* initialize map handle*/
79
0
    if((stat = nczmap_create(zinfo->controls.mapimpl,nc->path,nc->mode,zinfo->controls.flags,NULL,&zinfo->map)))
80
0
  goto done;
81
82
0
done:
83
0
    ncurifree(uri);
84
0
    NCJreclaim(json);
85
0
    nullfree(key);
86
0
    return ZUNTRACE(stat);
87
0
}
88
89
/**
90
@internal Open the topmost dataset object.
91
@param file - [in] the file struct
92
@param controls - [in] the fragment list in envv form from uri
93
@return NC_NOERR
94
@author Dennis Heimbigner
95
*/
96
97
int
98
ncz_open_dataset(NC_FILE_INFO_T* file, NClist* controls)
99
0
{
100
0
    int stat = NC_NOERR;
101
0
    NC* nc = NULL;
102
0
    NC_GRP_INFO_T* root = NULL;
103
0
    NCURI* uri = NULL;
104
0
    void* content = NULL;
105
0
    NCjson* json = NULL;
106
0
    NCZ_FILE_INFO_T* zinfo = NULL;
107
0
    int mode;
108
0
    NClist* modeargs = NULL;
109
0
    char* nczarr_version = NULL;
110
0
    char* zarr_format = NULL;
111
112
0
    ZTRACE(3,"file=%s controls=%s",file->hdr.name,(controls?nczprint_envv(controls):"null"));
113
114
    /* Extract info reachable via file */
115
0
    nc = (NC*)file->controller;
116
0
    mode = nc->mode;
117
118
0
    root = file->root_grp;
119
0
    assert(root != NULL && root->hdr.sort == NCGRP);
120
121
    /* Add struct to hold NCZ-specific file metadata. */
122
0
    if (!(file->format_file_info = calloc(1, sizeof(NCZ_FILE_INFO_T))))
123
0
        {stat = NC_ENOMEM; goto done;}
124
0
    zinfo = file->format_file_info;
125
126
    /* Fill in NCZ_FILE_INFO_T */
127
0
    zinfo->creating = 0;
128
0
    zinfo->common.file = file;
129
0
    zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
130
0
    if((zinfo->controllist=nclistclone(controls,1)) == NULL)
131
0
  {stat = NC_ENOMEM; goto done;}
132
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
133
134
    /* Add struct to hold NCZ-specific group info. */
135
0
    if (!(root->format_grp_info = calloc(1, sizeof(NCZ_GRP_INFO_T))))
136
0
        {stat = NC_ENOMEM; goto done;}
137
0
    ((NCZ_GRP_INFO_T*)root->format_grp_info)->common.file = file;
138
139
    /* Apply client controls */
140
0
    if((stat = applycontrols(zinfo))) goto done;
141
142
    /* initialize map handle*/
143
0
    if((stat = nczmap_open(zinfo->controls.mapimpl,nc->path,mode,zinfo->controls.flags,NULL,&zinfo->map)))
144
0
  goto done;
145
146
    /* Ok, try to read superblock */
147
0
    if((stat = ncz_read_superblock(file,&nczarr_version,&zarr_format))) goto done;
148
149
0
    if(nczarr_version == NULL) /* default */
150
0
        nczarr_version = strdup(NCZARRVERSION);
151
0
    if(zarr_format == NULL) /* default */
152
0
       zarr_format = strdup(ZARRVERSION);
153
    /* Extract the information from it */
154
0
    if(sscanf(zarr_format,"%d",&zinfo->zarr.zarr_version)!=1)
155
0
  {stat = NC_ENCZARR; goto done;}   
156
0
    if(sscanf(nczarr_version,"%lu.%lu.%lu",
157
0
        &zinfo->zarr.nczarr_version.major,
158
0
        &zinfo->zarr.nczarr_version.minor,
159
0
        &zinfo->zarr.nczarr_version.release) == 0)
160
0
  {stat = NC_ENCZARR; goto done;}
161
162
    /* Load auth info from rc file */
163
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
164
0
    if(uri) {
165
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
166
0
      goto done;
167
0
    }
168
169
0
done:
170
0
    nullfree(zarr_format);
171
0
    nullfree(nczarr_version);
172
0
    ncurifree(uri);
173
0
    nclistfreeall(modeargs);
174
0
    if(json) NCJreclaim(json);
175
0
    nullfree(content);
176
0
    return ZUNTRACE(stat);
177
0
}
178
179
/**
180
 * @internal Determine whether file is netCDF-4.
181
 *
182
 * For libzarr, this is always true.
183
 *
184
 * @param h5 Pointer to HDF5 file info struct.
185
 *
186
 * @returns NC_NOERR No error.
187
 * @author Dennis Heimbigner.
188
 */
189
int
190
NCZ_isnetcdf4(struct NC_FILE_INFO* h5)
191
0
{
192
0
    int isnc4 = 1;
193
0
    NC_UNUSED(h5);
194
0
    return isnc4;
195
0
}
196
197
/**
198
 * @internal Determine version info
199
 *
200
 * For libzarr, this is not well defined
201
 *
202
 * @param majorp Pointer to major version number
203
 * @param minorp Pointer to minor version number
204
 * @param releasep Pointer to release version number
205
 *
206
 * @returns NC_NOERR No error.
207
 * @author Dennis Heimbigner.
208
 */
209
int
210
NCZ_get_libversion(unsigned long* majorp, unsigned long* minorp,unsigned long* releasep)
211
1
{
212
1
    unsigned long m0,m1,m2;
213
1
    sscanf(NCZARRVERSION,"%lu.%lu.%lu",&m0,&m1,&m2);
214
1
    if(majorp) *majorp = m0;
215
1
    if(minorp) *minorp = m1;
216
1
    if(releasep) *releasep = m2;
217
1
    return NC_NOERR;
218
1
}
219
220
/**
221
 * @internal Determine "superblock" number.
222
 *
223
 * For libzarr, use the value of the major part of the nczarr version.
224
 *
225
 * @param superblocp Pointer to place to return superblock.
226
 * use the nczarr format version major as the superblock number.
227
 *
228
 * @returns NC_NOERR No error.
229
 * @author Dennis Heimbigner.
230
 */
231
int
232
NCZ_get_superblock(NC_FILE_INFO_T* file, int* superblockp)
233
0
{
234
0
    NCZ_FILE_INFO_T* zinfo = file->format_file_info;
235
0
    if(superblockp) *superblockp = zinfo->zarr.nczarr_version.major;
236
0
    return NC_NOERR;
237
0
}
238
239
/**************************************************/
240
/* Utilities */
241
242
static const char*
243
controllookup(NClist* controls, const char* key)
244
0
{
245
0
    size_t i;
246
0
    for(i=0;i<nclistlength(controls);i+=2) {
247
0
        const char* p = (char*)nclistget(controls,i);
248
0
  if(strcasecmp(key,p)==0) {
249
0
      return (const char*)nclistget(controls,i+1);
250
0
  }
251
0
    }
252
0
    return NULL;
253
0
}
254
255
256
static int
257
applycontrols(NCZ_FILE_INFO_T* zinfo)
258
0
{
259
0
    size_t i;
260
0
    int stat = NC_NOERR;
261
0
    const char* value = NULL;
262
0
    NClist* modelist = nclistnew();
263
0
    size64_t noflags = 0; /* track non-default negative flags */
264
265
0
    if((value = controllookup(zinfo->controllist,"mode")) != NULL) {
266
0
  if((stat = NCZ_comma_parse(value,modelist))) goto done;
267
0
    }
268
    /* Process the modelist first */
269
0
    zinfo->controls.mapimpl = NCZM_DEFAULT;
270
0
    zinfo->controls.flags |= FLAG_XARRAYDIMS; /* Always support XArray convention where possible */
271
0
    for(i=0;i<nclistlength(modelist);i++) {
272
0
        const char* p = nclistget(modelist,i);
273
0
  if(strcasecmp(p,PUREZARRCONTROL)==0)
274
0
      zinfo->controls.flags |= (FLAG_PUREZARR);
275
0
  else if(strcasecmp(p,XARRAYCONTROL)==0)
276
0
      zinfo->controls.flags |= FLAG_PUREZARR;
277
0
  else if(strcasecmp(p,NOXARRAYCONTROL)==0)
278
0
      noflags |= FLAG_XARRAYDIMS;
279
0
  else if(strcasecmp(p,"zip")==0) zinfo->controls.mapimpl = NCZM_ZIP;
280
0
  else if(strcasecmp(p,"file")==0) zinfo->controls.mapimpl = NCZM_FILE;
281
0
  else if(strcasecmp(p,"s3")==0) zinfo->controls.mapimpl = NCZM_S3;
282
0
    }
283
    /* Apply negative controls by turning off negative flags */
284
    /* This is necessary to avoid order dependence of mode flags when both positive and negative flags are defined */
285
0
    zinfo->controls.flags &= (~noflags);
286
287
    /* Process other controls */
288
0
    if((value = controllookup(zinfo->controllist,"log")) != NULL) {
289
0
  zinfo->controls.flags |= FLAG_LOGGING;
290
0
        ncsetloglevel(NCLOGNOTE);
291
0
    }
292
0
    if((value = controllookup(zinfo->controllist,"show")) != NULL) {
293
0
  if(strcasecmp(value,"fetch")==0)
294
0
      zinfo->controls.flags |= FLAG_SHOWFETCH;
295
0
    }
296
0
done:
297
0
    nclistfreeall(modelist);
298
0
    return stat;
299
0
}