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;
201 if((ncstat = NC4_read_ncproperties(file,&propstring)))
goto done;
202 provenance->ncproperties = propstring;
206 nullfree(propstring);
208 LOG((0,
"Could not create _NCProperties attribute"));
225 NC4_write_provenance(NC_FILE_INFO_T* file)
236 NC4_read_ncproperties(NC_FILE_INFO_T* h5,
char** propstring)
239 hid_t hdf5grpid = -1;
248 LOG((5,
"%s", __func__));
250 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
252 if(H5Aexists(hdf5grpid,NCPROPS) <= 0) {
258 attid = H5Aopen_name(hdf5grpid, NCPROPS);
260 aspace = H5Aget_space(attid);
261 atype = H5Aget_type(attid);
263 t_class = H5Tget_class(atype);
264 if(t_class != H5T_STRING)
266 size = H5Tget_size(atype);
269 text = (
char*)malloc(1+(
size_t)size);
272 if((ntype = H5Tget_native_type(atype, H5T_DIR_DEFAULT)) < 0)
274 if((H5Aread(attid, ntype, text)) < 0)
277 text[(size_t)size] =
'\0';
278 if(propstring) {*propstring = text; text = NULL;}
281 if(text != NULL) free(text);
283 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
284 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
285 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
286 if(ntype > 0 && H5Tclose(ntype) < 0) retval =
NC_EHDFERR;
291 LOG((0,
"Invalid _NCProperties attribute: ignored"));
301 #ifdef SUPPRESSNCPROPERTY
304 int retval = NC_NOERR;
305 hid_t hdf5grpid = -1;
310 NC4_Provenance* prov = &h5->provenance;
312 LOG((5,
"%s", __func__));
318 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
320 if(H5Aexists(hdf5grpid,NCPROPS) > 0)
324 if(prov->ncproperties != NULL) {
326 if ((atype = H5Tcopy(H5T_C_S1)) < 0)
328 if (H5Tset_strpad(atype, H5T_STR_NULLTERM) < 0)
330 if(H5Tset_cset(atype, H5T_CSET_ASCII) < 0)
332 len = strlen(prov->ncproperties);
333 if(H5Tset_size(atype, len) < 0)
336 if((aspace = H5Screate(H5S_SCALAR)) < 0)
338 if ((attid = H5Acreate(hdf5grpid, NCPROPS, atype, aspace, H5P_DEFAULT)) < 0)
340 if (H5Awrite(attid, atype, prov->ncproperties) < 0)
346 hsize_t dsize, tsize;
347 typev = H5Aget_type(attid);
348 spacev = H5Aget_space(attid);
349 dsize = H5Aget_storage_size(attid);
350 tsize = H5Tget_size(typev);
351 fprintf(stderr,
"dsize=%lu tsize=%lu\n",(
unsigned long)dsize,(
unsigned long)tsize);
358 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
359 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
360 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
371 LOG((0,
"Invalid _NCProperties attribute"));
385 ncprintprovenance(NC4_Provenance* info)
387 fprintf(stderr,
"[%p] version=%d superblockversion=%d ncproperties=|%s|\n",
390 info->superblockversion,
391 (info->ncproperties==NULL?
"":info->ncproperties));
404 NC4_clear_provenance(NC4_Provenance* prov)
406 LOG((5,
"%s", __func__));
409 nullfree(prov->ncproperties);
410 memset(prov,0,
sizeof(NC4_Provenance));
427 properties_parse(
const char* text0, NClist* pairs)
434 if(text0 == NULL || strlen(text0) == 0)
437 text = strdup(text0);
442 if(*p == NCPROPSSEP1)
454 q = locate(p,NCPROPSSEP2);
465 nclistpush(pairs,strdup(name));
466 nclistpush(pairs,strdup(value));
477 locate(
char* p,
char tag)
482 for(next = p;(c = *next);next++) {
485 else if(c ==
'\\' && next[1] !=
'\0')
493 escapify(NCbytes* buffer,
const char* s)
497 if(strchr(ESCAPECHARS,*p) != NULL)
498 ncbytesappend(buffer,
'\\');
499 ncbytesappend(buffer,*p);
517 build_propstring(
int version, NClist* list,
char** spropp)
521 NCbytes* buffer = NULL;
524 LOG((5,
"%s version=%d", __func__, version));
526 if(spropp != NULL) *spropp = NULL;
528 if(version == 0 || version > NCPROPS_VERSION)
533 if((buffer = ncbytesnew()) == NULL)
537 ncbytescat(buffer,NCPVERSION);
538 ncbytesappend(buffer,
'=');
540 snprintf(sversion,
sizeof(sversion),
"%d",NCPROPS_VERSION);
541 ncbytescat(buffer,sversion);
543 for(i=0;i<nclistlength(list);i+=2) {
545 name = nclistget(list,i);
546 if(name == NULL)
continue;
547 value = nclistget(list,i+1);
548 ncbytesappend(buffer,NCPROPSSEP2);
549 escapify(buffer,name);
550 ncbytesappend(buffer,
'=');
551 escapify(buffer,value);
555 if(spropp) *spropp = ncbytesextract(buffer);
558 if(buffer != NULL) ncbytesfree(buffer);
563 properties_getversion(
const char* propstring,
int* versionp)
568 if(propstring == NULL || strlen(propstring) < strlen(
"version=") + strlen(
"1"))
570 if(memcmp(propstring,
"version=",strlen(
"version=")) != 0)
572 propstring += strlen(
"version=");
574 version = atoi(propstring);
577 if(versionp) *versionp = version;
595 parse_provenance(NC4_Provenance* prov)
603 LOG((5,
"%s: prov 0x%x", __func__, prov));
605 if(prov->ncproperty == NULL || strlen(prov->ncproperty) < strlen(
"version="))
607 if((list = nclistnew()) == NULL)
611 if(prov->version > 0 && prov->version <= NCPROPS_VERSION) {
612 if((ncstat=properties_parse(prov->ncproperty,list)))
615 if(nclistlength(list) < 2)
618 nclistremove(list,0);
619 nclistremove(list,0);
626 for(i=0;i<nclistlength(list);i+=2) {
627 char* newname = NULL;
628 name = nclistget(list,i);
629 if(name == NULL)
continue;
630 if(strcmp(name,NCPNCLIB1) == 0)
632 else if(strcmp(name,NCPHDF5LIB1) == 0)
633 newname = NCPHDF5LIB2;
636 nclistset(list,i,strdup(newname));
637 if(name) {free(name); name = NULL;}
642 prov->properties = list;
647 if(name != NULL) free(name);
648 if(value != NULL) free(value);
662 NC4_free_provenance(NC4_Provenance* prov)
664 LOG((5,
"%s", __func__));
667 NC4_clear_provenance(prov);
674 propinfo_default(NC4_Properties* dst,
const NC4_Properties* dfalt)
677 if(dst->properties == NULL) {
678 dst->properties = nclistnew();
679 if(dst->properties == NULL)
return NC_ENOMEM;
681 dst->version = dfalt->version;
682 for(i=0;i<nclistlength(dfalt->properties);i++) {
683 char* s = nclistget(dfalt->properties,i);
686 nclistpush(dst->properties,s);