11 #include "nc4internal.h"
12 #include "hdf5internal.h"
13 #include "nc_provenance.h"
20 #undef SUPPRESSNCPROPS
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;}}
35 static int NC4_read_ncproperties(NC_FILE_INFO_T* h5,
char** propstring);
38 static int globalpropinitialized = 0;
39 static NC4_Provenance globalprovenance;
51 NC4_provenance_init(
void)
56 unsigned major,minor,release;
57 NCbytes* buffer = NULL;
61 if(globalpropinitialized)
67 memset((
void*)&globalprovenance,0,
sizeof(NC4_Provenance));
68 globalprovenance.version = NCPROPS_VERSION;
70 buffer = ncbytesnew();
73 ncbytescat(buffer,NCPVERSION);
74 ncbytescat(buffer,
"=");
76 snprintf(printbuf,
sizeof(printbuf),
"%d",globalprovenance.version);
77 ncbytescat(buffer,printbuf);
80 ncbytesappend(buffer,NCPROPSSEP2);
81 ncbytescat(buffer,NCPNCLIB2);
82 ncbytescat(buffer,
"=");
83 ncbytescat(buffer,PACKAGE_VERSION);
86 ncbytesappend(buffer,NCPROPSSEP2);
87 ncbytescat(buffer,NCPHDF5LIB2);
88 ncbytescat(buffer,
"=");
89 if((stat = NC4_hdf5get_libversion(&major,&minor,&release)))
goto done;
90 snprintf(printbuf,
sizeof(printbuf),
"%1u.%1u.%1u",major,minor,release);
91 ncbytescat(buffer,printbuf);
93 #ifdef NCPROPERTIES_EXTRA
95 p = NCPROPERTIES_EXTRA;
96 if(p[0] == NCPROPSSEP2) p++;
97 ncbytesappend(buffer,NCPROPSSEP2);
101 globalprovenance.ncproperties = ncbytesextract(buffer);
105 if(name != NULL) free(name);
106 if(value != NULL) free(value);
108 globalpropinitialized = 1;
119 NC4_provenance_finalize(
void)
121 return NC4_clear_provenance(&globalprovenance);
138 NC4_new_provenance(NC_FILE_INFO_T* file)
141 NC4_Provenance* provenance = NULL;
144 LOG((5,
"%s: ncid 0x%x", __func__, file->root_grp->hdr.id));
146 assert(file->provenance.ncproperties == NULL);
148 provenance = &file->provenance;
149 memset(provenance,0,
sizeof(NC4_Provenance));
152 provenance->version = globalprovenance.version;
155 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
goto done;
156 provenance->superblockversion = superblock;
158 if(globalprovenance.ncproperties != NULL) {
159 if((provenance->ncproperties = strdup(globalprovenance.ncproperties)) == NULL)
165 LOG((0,
"Could not create _NCProperties attribute"));
182 NC4_read_provenance(NC_FILE_INFO_T* file)
185 NC4_Provenance* provenance = NULL;
187 char* propstring = NULL;
189 LOG((5,
"%s: ncid 0x%x", __func__, file->root_grp->hdr.id));
191 assert(file->provenance.version == 0);
193 provenance = &file->provenance;
194 memset(provenance,0,
sizeof(NC4_Provenance));
197 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
goto done;
198 provenance->superblockversion = superblock;
203 if((ncstat = NC4_read_ncproperties(file,&propstring)))
goto done;
204 provenance->ncproperties = propstring;
208 nullfree(propstring);
210 LOG((0,
"Could not create _NCProperties attribute"));
227 NC4_write_provenance(NC_FILE_INFO_T* file)
238 NC4_read_ncproperties(NC_FILE_INFO_T* h5,
char** propstring)
241 hid_t hdf5grpid = -1;
250 LOG((5,
"%s", __func__));
252 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
254 if(H5Aexists(hdf5grpid,NCPROPS) <= 0) {
260 attid = H5Aopen_name(hdf5grpid, NCPROPS);
262 aspace = H5Aget_space(attid);
263 atype = H5Aget_type(attid);
265 t_class = H5Tget_class(atype);
266 if(t_class != H5T_STRING)
268 size = H5Tget_size(atype);
271 text = (
char*)malloc(1+(
size_t)size);
274 if((ntype = H5Tget_native_type(atype, H5T_DIR_DEFAULT)) < 0)
276 if((H5Aread(attid, ntype, text)) < 0)
279 text[(size_t)size] =
'\0';
280 if(propstring) {*propstring = text; text = NULL;}
283 if(text != NULL) free(text);
285 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
286 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
287 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
288 if(ntype > 0 && H5Tclose(ntype) < 0) retval =
NC_EHDFERR;
293 LOG((0,
"Invalid _NCProperties attribute: ignored"));
303 #ifdef SUPPRESSNCPROPERTY
306 int retval = NC_NOERR;
307 hid_t hdf5grpid = -1;
312 NC4_Provenance* prov = &h5->provenance;
314 LOG((5,
"%s", __func__));
320 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
322 if(H5Aexists(hdf5grpid,NCPROPS) > 0)
326 if(prov->ncproperties != NULL) {
328 if ((atype = H5Tcopy(H5T_C_S1)) < 0)
330 if (H5Tset_strpad(atype, H5T_STR_NULLTERM) < 0)
332 if(H5Tset_cset(atype, H5T_CSET_ASCII) < 0)
334 len = strlen(prov->ncproperties);
335 if(H5Tset_size(atype, len) < 0)
338 if((aspace = H5Screate(H5S_SCALAR)) < 0)
340 if ((attid = H5Acreate(hdf5grpid, NCPROPS, atype, aspace, H5P_DEFAULT)) < 0)
342 if (H5Awrite(attid, atype, prov->ncproperties) < 0)
348 hsize_t dsize, tsize;
349 typev = H5Aget_type(attid);
350 spacev = H5Aget_space(attid);
351 dsize = H5Aget_storage_size(attid);
352 tsize = H5Tget_size(typev);
353 fprintf(stderr,
"dsize=%lu tsize=%lu\n",(
unsigned long)dsize,(
unsigned long)tsize);
360 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
361 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
362 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
373 LOG((0,
"Invalid _NCProperties attribute"));
387 ncprintprovenance(NC4_Provenance* info)
389 fprintf(stderr,
"[%p] version=%d superblockversion=%d ncproperties=|%s|\n",
392 info->superblockversion,
393 (info->ncproperties==NULL?
"":info->ncproperties));
406 NC4_clear_provenance(NC4_Provenance* prov)
408 LOG((5,
"%s", __func__));
411 nullfree(prov->ncproperties);
412 memset(prov,0,
sizeof(NC4_Provenance));
429 properties_parse(
const char* text0, NClist* pairs)
436 if(text0 == NULL || strlen(text0) == 0)
439 text = strdup(text0);
444 if(*p == NCPROPSSEP1)
456 q = locate(p,NCPROPSSEP2);
467 nclistpush(pairs,strdup(name));
468 nclistpush(pairs,strdup(value));
479 locate(
char* p,
char tag)
484 for(next = p;(c = *next);next++) {
487 else if(c ==
'\\' && next[1] !=
'\0')
495 escapify(NCbytes* buffer,
const char* s)
499 if(strchr(ESCAPECHARS,*p) != NULL)
500 ncbytesappend(buffer,
'\\');
501 ncbytesappend(buffer,*p);
519 build_propstring(
int version, NClist* list,
char** spropp)
523 NCbytes* buffer = NULL;
526 LOG((5,
"%s version=%d", __func__, version));
528 if(spropp != NULL) *spropp = NULL;
530 if(version == 0 || version > NCPROPS_VERSION)
535 if((buffer = ncbytesnew()) == NULL)
539 ncbytescat(buffer,NCPVERSION);
540 ncbytesappend(buffer,
'=');
542 snprintf(sversion,
sizeof(sversion),
"%d",NCPROPS_VERSION);
543 ncbytescat(buffer,sversion);
545 for(i=0;i<nclistlength(list);i+=2) {
547 name = nclistget(list,i);
548 if(name == NULL)
continue;
549 value = nclistget(list,i+1);
550 ncbytesappend(buffer,NCPROPSSEP2);
551 escapify(buffer,name);
552 ncbytesappend(buffer,
'=');
553 escapify(buffer,value);
557 if(spropp) *spropp = ncbytesextract(buffer);
560 if(buffer != NULL) ncbytesfree(buffer);
565 properties_getversion(
const char* propstring,
int* versionp)
570 if(propstring == NULL || strlen(propstring) < strlen(
"version=") + strlen(
"1"))
572 if(memcmp(propstring,
"version=",strlen(
"version=")) != 0)
574 propstring += strlen(
"version=");
576 version = atoi(propstring);
579 if(versionp) *versionp = version;
597 parse_provenance(NC4_Provenance* prov)
605 LOG((5,
"%s: prov 0x%x", __func__, prov));
607 if(prov->ncproperty == NULL || strlen(prov->ncproperty) < strlen(
"version="))
609 if((list = nclistnew()) == NULL)
613 if(prov->version > 0 && prov->version <= NCPROPS_VERSION) {
614 if((ncstat=properties_parse(prov->ncproperty,list)))
617 if(nclistlength(list) < 2)
620 nclistremove(list,0);
621 nclistremove(list,0);
628 for(i=0;i<nclistlength(list);i+=2) {
629 char* newname = NULL;
630 name = nclistget(list,i);
631 if(name == NULL)
continue;
632 if(strcmp(name,NCPNCLIB1) == 0)
634 else if(strcmp(name,NCPHDF5LIB1) == 0)
635 newname = NCPHDF5LIB2;
638 nclistset(list,i,strdup(newname));
639 if(name) {free(name); name = NULL;}
644 prov->properties = list;
649 if(name != NULL) free(name);
650 if(value != NULL) free(value);
664 NC4_free_provenance(NC4_Provenance* prov)
666 LOG((5,
"%s", __func__));
669 NC4_clear_provenance(prov);
676 propinfo_default(NC4_Properties* dst,
const NC4_Properties* dfalt)
679 if(dst->properties == NULL) {
680 dst->properties = nclistnew();
681 if(dst->properties == NULL)
return NC_ENOMEM;
683 dst->version = dfalt->version;
684 for(i=0;i<nclistlength(dfalt->properties);i++) {
685 char* s = nclistget(dfalt->properties,i);
688 nclistpush(dst->properties,s);