11#include "nc4internal.h"
12#include "hdf5internal.h"
13#include "nc_provenance.h"
23#define NCPROPS_MAX_NAME 1024
24#define NCPROPS_MAX_VALUE 1024
25#define HDF5_MAX_NAME 1024
27#define ESCAPECHARS "\\=|,"
30#define NCHECK(expr) {if((expr)!=NC_NOERR) {goto done;}}
33#define HCHECK(expr) {if((expr)<0) {ncstat = NC_EHDFERR; goto done;}}
35static int NC4_read_ncproperties(NC_FILE_INFO_T* h5,
char** propstring);
38static int globalpropinitialized = 0;
39static NC4_Provenance globalprovenance;
51NC4_provenance_init(
void)
56 unsigned major,minor,release;
57 NCbytes* buffer = NULL;
60 if(globalpropinitialized)
66 memset((
void*)&globalprovenance,0,
sizeof(NC4_Provenance));
67 globalprovenance.version = NCPROPS_VERSION;
69 buffer = ncbytesnew();
72 ncbytescat(buffer,NCPVERSION);
73 ncbytescat(buffer,
"=");
75 snprintf(printbuf,
sizeof(printbuf),
"%d",globalprovenance.version);
76 ncbytescat(buffer,printbuf);
79 ncbytesappend(buffer,NCPROPSSEP2);
80 ncbytescat(buffer,NCPNCLIB2);
81 ncbytescat(buffer,
"=");
82 ncbytescat(buffer,PACKAGE_VERSION);
85 ncbytesappend(buffer,NCPROPSSEP2);
86 ncbytescat(buffer,NCPHDF5LIB2);
87 ncbytescat(buffer,
"=");
88 if((stat = NC4_hdf5get_libversion(&major,&minor,&release)))
goto done;
89 snprintf(printbuf,
sizeof(printbuf),
"%1u.%1u.%1u",major,minor,release);
90 ncbytescat(buffer,printbuf);
92#ifdef NCPROPERTIES_EXTRA
93 if(NCPROPERTIES_EXTRA != NULL && strlen(NCPROPERTIES_EXTRA) > 0)
96 p = NCPROPERTIES_EXTRA;
97 if(p[0] == NCPROPSSEP2) p++;
98 ncbytesappend(buffer,NCPROPSSEP2);
103 globalprovenance.ncproperties = ncbytesextract(buffer);
107 if(name != NULL) free(name);
108 if(value != NULL) free(value);
110 globalpropinitialized = 1;
121NC4_provenance_finalize(
void)
123 return NC4_clear_provenance(&globalprovenance);
140NC4_new_provenance(NC_FILE_INFO_T* file)
143 NC4_Provenance* provenance = NULL;
146 LOG((5,
"%s: ncid 0x%x", __func__, file->root_grp->hdr.id));
148 assert(file->provenance.ncproperties == NULL);
150 provenance = &file->provenance;
151 memset(provenance,0,
sizeof(NC4_Provenance));
154 provenance->version = globalprovenance.version;
157 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
goto done;
158 provenance->superblockversion = superblock;
160 if(globalprovenance.ncproperties != NULL) {
161 if((provenance->ncproperties = strdup(globalprovenance.ncproperties)) == NULL)
167 LOG((0,
"Could not create _NCProperties attribute"));
184NC4_read_provenance(NC_FILE_INFO_T* file)
187 NC4_Provenance* provenance = NULL;
189 char* propstring = NULL;
191 LOG((5,
"%s: ncid 0x%x", __func__, file->root_grp->hdr.id));
193 assert(file->provenance.version == 0);
195 provenance = &file->provenance;
196 memset(provenance,0,
sizeof(NC4_Provenance));
199 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
goto done;
200 provenance->superblockversion = superblock;
205 if((ncstat = NC4_read_ncproperties(file,&propstring)))
goto done;
206 provenance->ncproperties = propstring;
210 nullfree(propstring);
212 LOG((0,
"Could not create _NCProperties attribute"));
229NC4_write_provenance(NC_FILE_INFO_T* file)
240NC4_read_ncproperties(NC_FILE_INFO_T* h5,
char** propstring)
243 hid_t hdf5grpid = -1;
252 LOG((5,
"%s", __func__));
254 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
256 if(H5Aexists(hdf5grpid,NCPROPS) <= 0) {
262 attid = H5Aopen_by_name(hdf5grpid,
".", NCPROPS, H5P_DEFAULT, H5P_DEFAULT);
264 aspace = H5Aget_space(attid);
265 atype = H5Aget_type(attid);
267 t_class = H5Tget_class(atype);
268 if(t_class != H5T_STRING)
270 size = H5Tget_size(atype);
273 text = (
char*)malloc(1+(
size_t)size);
276 if((ntype = H5Tget_native_type(atype, H5T_DIR_DEFAULT)) < 0)
278 if((H5Aread(attid, ntype, text)) < 0)
281 text[(size_t)size] =
'\0';
282 if(propstring) {*propstring = text; text = NULL;}
285 if(text != NULL) free(text);
287 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
288 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
289 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
290 if(ntype > 0 && H5Tclose(ntype) < 0) retval =
NC_EHDFERR;
295 LOG((0,
"Invalid _NCProperties attribute: ignored"));
305#ifdef SUPPRESSNCPROPERTY
309 hid_t hdf5grpid = -1;
314 NC4_Provenance* prov = &h5->provenance;
316 LOG((5,
"%s", __func__));
322 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
324 if(H5Aexists(hdf5grpid,NCPROPS) > 0)
328 if(prov->ncproperties != NULL) {
330 if ((atype = H5Tcopy(H5T_C_S1)) < 0)
332 if (H5Tset_strpad(atype, H5T_STR_NULLTERM) < 0)
334 if(H5Tset_cset(atype, H5T_CSET_ASCII) < 0)
336 len = strlen(prov->ncproperties);
337 if(H5Tset_size(atype, len) < 0)
340 if((aspace = H5Screate(H5S_SCALAR)) < 0)
342 if ((attid = H5Acreate1(hdf5grpid, NCPROPS, atype, aspace, H5P_DEFAULT)) < 0)
344 if (H5Awrite(attid, atype, prov->ncproperties) < 0)
350 hsize_t dsize, tsize;
351 typev = H5Aget_type(attid);
352 spacev = H5Aget_space(attid);
353 dsize = H5Aget_storage_size(attid);
354 tsize = H5Tget_size(typev);
355 fprintf(stderr,
"dsize=%lu tsize=%lu\n",(
unsigned long)dsize,(
unsigned long)tsize);
362 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
363 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
364 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
375 LOG((0,
"Invalid _NCProperties attribute"));
389ncprintprovenance(NC4_Provenance* info)
391 fprintf(stderr,
"[%p] version=%d superblockversion=%d ncproperties=|%s|\n",
394 info->superblockversion,
395 (info->ncproperties==NULL?
"":info->ncproperties));
408NC4_clear_provenance(NC4_Provenance* prov)
410 LOG((5,
"%s", __func__));
413 nullfree(prov->ncproperties);
414 memset(prov,0,
sizeof(NC4_Provenance));
431properties_parse(
const char* text0, NClist* pairs)
438 if(text0 == NULL || strlen(text0) == 0)
441 text = strdup(text0);
446 if(*p == NCPROPSSEP1)
458 q = locate(p,NCPROPSSEP2);
469 nclistpush(pairs,strdup(name));
470 nclistpush(pairs,strdup(value));
481locate(
char* p,
char tag)
486 for(next = p;(c = *next);next++) {
489 else if(c ==
'\\' && next[1] !=
'\0')
497escapify(NCbytes* buffer,
const char* s)
501 if(strchr(ESCAPECHARS,*p) != NULL)
502 ncbytesappend(buffer,
'\\');
503 ncbytesappend(buffer,*p);
521build_propstring(
int version, NClist* list,
char** spropp)
525 NCbytes* buffer = NULL;
528 LOG((5,
"%s version=%d", __func__, version));
530 if(spropp != NULL) *spropp = NULL;
532 if(version == 0 || version > NCPROPS_VERSION)
537 if((buffer = ncbytesnew()) == NULL)
541 ncbytescat(buffer,NCPVERSION);
542 ncbytesappend(buffer,
'=');
544 snprintf(sversion,
sizeof(sversion),
"%d",NCPROPS_VERSION);
545 ncbytescat(buffer,sversion);
547 for(i=0;i<nclistlength(list);i+=2) {
549 name = nclistget(list,i);
550 if(name == NULL)
continue;
551 value = nclistget(list,i+1);
552 ncbytesappend(buffer,NCPROPSSEP2);
553 escapify(buffer,name);
554 ncbytesappend(buffer,
'=');
555 escapify(buffer,value);
559 if(spropp) *spropp = ncbytesextract(buffer);
562 if(buffer != NULL) ncbytesfree(buffer);
567properties_getversion(
const char* propstring,
int* versionp)
572 if(propstring == NULL || strlen(propstring) < strlen(
"version=") + strlen(
"1"))
574 if(memcmp(propstring,
"version=",strlen(
"version=")) != 0)
576 propstring += strlen(
"version=");
578 version = atoi(propstring);
581 if(versionp) *versionp = version;
599parse_provenance(NC4_Provenance* prov)
607 LOG((5,
"%s: prov 0x%x", __func__, prov));
609 if(prov->ncproperty == NULL || strlen(prov->ncproperty) < strlen(
"version="))
611 if((list = nclistnew()) == NULL)
615 if(prov->version > 0 && prov->version <= NCPROPS_VERSION) {
616 if((ncstat=properties_parse(prov->ncproperty,list)))
619 if(nclistlength(list) < 2)
622 nclistremove(list,0);
623 nclistremove(list,0);
630 for(i=0;i<nclistlength(list);i+=2) {
631 char* newname = NULL;
632 name = nclistget(list,i);
633 if(name == NULL)
continue;
634 if(strcmp(name,NCPNCLIB1) == 0)
636 else if(strcmp(name,NCPHDF5LIB1) == 0)
637 newname = NCPHDF5LIB2;
640 nclistset(list,i,strdup(newname));
641 if(name) {free(name); name = NULL;}
646 prov->properties = list;
651 if(name != NULL) free(name);
652 if(value != NULL) free(value);
666NC4_free_provenance(NC4_Provenance* prov)
668 LOG((5,
"%s", __func__));
671 NC4_clear_provenance(prov);
678propinfo_default(NC4_Properties* dst,
const NC4_Properties* dfalt)
681 if(dst->properties == NULL) {
682 dst->properties = nclistnew();
683 if(dst->properties == NULL)
return NC_ENOMEM;
685 dst->version = dfalt->version;
686 for(i=0;i<nclistlength(dfalt->properties);i++) {
687 char* s = nclistget(dfalt->properties,i);
690 nclistpush(dst->properties,s);
static int NC4_write_ncproperties(NC_FILE_INFO_T *h5)
#define NC_EPERM
Write to read only.
#define NC_ENOMEM
Memory allocation (malloc) failure.
#define NC_EHDFERR
Error at HDF5 layer.
#define NC_EFILEMETA
Problem with file metadata.
#define NC_EINVAL
Invalid Argument.
#define NC_NOERR
No Error.