11 #include "nc4internal.h" 12 #include "hdf5internal.h" 17 #define NCPROPS_MAX_NAME 1024 18 #define NCPROPS_MAX_VALUE 1024 19 #define HDF5_MAX_NAME 1024 21 #define ESCAPECHARS "\\=|," 24 #define NCHECK(expr) {if((expr)!=NC_NOERR) {goto done;}} 27 #define HCHECK(expr) {if((expr)<0) {ncstat = NC_EHDFERR; goto done;}} 29 static int globalpropinitialized = 0;
33 static int properties_parse(
const char* text0, NClist* pairs);
45 NC4_provenance_init(
void)
52 unsigned major,minor,release;
54 if(globalpropinitialized)
61 globalpropinfo.version = NCPROPS_VERSION;
62 globalpropinfo.properties = nclistnew();
63 if(globalpropinfo.properties == NULL)
67 if((name = strdup(NCPNCLIB2)) == NULL)
69 nclistpush(globalpropinfo.properties,name);
72 if((value = strdup(PACKAGE_VERSION)) == NULL)
74 nclistpush(globalpropinfo.properties,value);
78 if((name = strdup(NCPHDF5LIB2)) == NULL)
80 nclistpush(globalpropinfo.properties,name);
83 stat = NC4_hdf5get_libversion(&major,&minor,&release);
87 snprintf(sversion,
sizeof(sversion),
"%1u.%1u.%1u",major,minor,release);
88 if((value = strdup(sversion)) == NULL)
91 nclistpush(globalpropinfo.properties,value);
97 if(other == NULL) {stat =
NC_ENOMEM;
goto done;}
99 stat = properties_parse(NCPROPERTIES_EXTRA,other);
103 for(i=0;i<nclistlength(other);i++)
104 nclistpush(globalpropinfo.properties,strdup(nclistget(other,i)));
105 nclistfreeall(other);
109 if(name != NULL) free(name);
110 if(value != NULL) free(value);
112 nclistfreeall(other);
113 if(stat && globalpropinfo.properties != NULL) {
114 nclistfreeall(globalpropinfo.properties);
115 globalpropinfo.properties = NULL;
118 globalpropinitialized = 1;
126 locate(
char* p,
char tag)
131 for(next = p;(c = *next);next++) {
134 else if(c ==
'\\' && next[1] !=
'\0')
147 NC4_provenance_finalize(
void)
149 nclistfreeall(globalpropinfo.properties);
163 properties_parse(
const char* text0, NClist* pairs)
170 if(text0 == NULL || strlen(text0) == 0)
173 text = strdup(text0);
178 if(*p == NCPROPSSEP1)
190 q = locate(p,NCPROPSSEP2);
201 nclistpush(pairs,strdup(name));
202 nclistpush(pairs,strdup(value));
212 escapify(NCbytes* buffer,
const char* s)
216 if(strchr(ESCAPECHARS,*p) != NULL)
217 ncbytesappend(buffer,
'\\');
218 ncbytesappend(buffer,*p);
224 propinfo_default(
struct NCPROPINFO* dst,
const struct NCPROPINFO* dfalt)
227 if(dst->properties == NULL) {
228 dst->properties = nclistnew();
229 if(dst->properties == NULL)
return NC_ENOMEM;
231 dst->version = dfalt->version;
232 for(i=0;i<nclistlength(dfalt->properties);i++) {
233 char* s = nclistget(dfalt->properties,i);
236 nclistpush(dst->properties,s);
254 NC4_buildpropinfo(
struct NCPROPINFO* info,
char** propdatap)
258 NCbytes* buffer = NULL;
261 if(info == NULL || info->version == 0 || propdatap == NULL)
266 buffer = ncbytesnew();
267 if(!buffer) {stat =
NC_ENOMEM;
goto done;}
270 ncbytescat(buffer,NCPVERSION);
271 ncbytesappend(buffer,
'=');
272 snprintf(sversion,
sizeof(sversion),
"%d",info->version);
273 ncbytescat(buffer,sversion);
275 for(i=0;i<nclistlength(info->properties);i+=2) {
277 name = nclistget(info->properties,i);
278 if(name == NULL)
continue;
279 value = nclistget(info->properties,i+1);
280 ncbytesappend(buffer,NCPROPSSEP2);
281 escapify(buffer,name);
282 ncbytesappend(buffer,
'=');
283 escapify(buffer,value);
287 *propdatap = ncbytesextract(buffer);
290 if(buffer != NULL) ncbytesfree(buffer);
304 NC4_put_ncproperties(NC_FILE_INFO_T* file)
310 grp = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
312 if(H5Aexists(grp,NCPROPS) <= 0) {
313 ncstat = NC4_buildpropinfo(&h5->fileinfo->propattr,&text);
314 if(text == NULL || ncstat !=
NC_NOERR) {
318 HCHECK((atype = H5Tcopy(H5T_C_S1)));
319 HCHECK((H5Tset_cset(atype, H5T_CSET_ASCII)));
320 HCHECK((H5Tset_size(atype, strlen(text)+1)));
321 HCHECK((aspace = H5Screate(H5S_SCALAR)));
322 HCHECK((attid = H5Acreate(grp, NCPROPS, atype, aspace, H5P_DEFAULT)));
323 HCHECK((H5Awrite(attid, atype, text)));
331 if(attid >= 0) HCHECK((H5Aclose(attid)));
332 if(aspace >= 0) HCHECK((H5Sclose(aspace)));
333 if(atype >= 0) HCHECK((H5Tclose(atype)));
354 NC4_set_provenance(NC_FILE_INFO_T* file,
const struct NCPROPINFO* dfalt)
357 struct NCPROVENANCE* provenance = NULL;
360 assert(file->provenance == NULL);
361 provenance = calloc(1,
sizeof(
struct NCPROVENANCE));
362 if(provenance == NULL) {ncstat =
NC_ENOMEM;
goto done;}
365 provenance->propattr.version = globalpropinfo.version;
367 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
369 provenance->superblockversion = superblock;
372 provenance->propattr.properties = nclistnew();
373 if(provenance->propattr.properties == NULL)
378 for(i=0;i<nclistlength(dfalt->properties);i++) {
379 char* prop = nclistget(dfalt->properties,i);
382 if(prop == NULL) {ncstat =
NC_ENOMEM;
goto done;}
383 nclistpush(provenance->propattr.properties,prop);
390 LOG((0,
"Could not create _NCProperties attribute"));
391 (void)NC4_free_provenance(provenance);
393 file->provenance = provenance;
414 NC4_get_provenance(NC_FILE_INFO_T* file,
const char* propstring,
const struct NCPROPINFO* dfalt)
417 struct NCPROVENANCE* provenance;
423 assert(file->provenance == NULL);
424 if((file->provenance = calloc(1,
sizeof(
struct NCPROVENANCE))) == NULL)
426 provenance = file->provenance;
427 if((provenance->propattr.properties = nclistnew()) == NULL)
431 if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
433 provenance->superblockversion = superblock;
435 if(propstring == NULL) {
437 if((ncstat=propinfo_default(&provenance->propattr,dfalt)))
440 NClist* list = provenance->propattr.properties;
441 if((ncstat=properties_parse(propstring,list)))
444 if(nclistlength(list) < 2)
447 name = nclistremove(list,0);
448 value = nclistremove(list,0);
449 if(strcmp(name,NCPVERSION) == 0) {
450 if(sscanf(value,
"%d",&v) != 1)
452 if(v <= 0 || v > NCPROPS_VERSION)
454 provenance->propattr.version = v;
459 if(provenance->propattr.version == 1) {
461 for(i=0;i<nclistlength(list);i+=2) {
462 char* newname = NULL;
463 name = nclistget(list,i);
464 if(name == NULL)
continue;
465 if(strcmp(name,NCPNCLIB1) == 0)
467 else if(strcmp(name,NCPHDF5LIB1) == 0)
468 newname = NCPHDF5LIB2;
471 nclistset(list,i,strdup(newname));
478 if(name != NULL) free(name);
479 if(value != NULL) free(value);
493 NC4_free_provenance(
struct NCPROVENANCE* prov)
496 if(prov->propattr.properties != NULL)
497 nclistfreeall(prov->propattr.properties);
498 prov->propattr.properties = NULL;
505 NC4_read_ncproperties(NC_FILE_INFO_T* h5)
508 hid_t hdf5grpid = -1;
517 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
519 if(H5Aexists(hdf5grpid,NCPROPS) <= 0) {
521 retval=NC4_get_provenance(h5,NULL,&globalpropinfo);
526 attid = H5Aopen_name(hdf5grpid, NCPROPS);
528 aspace = H5Aget_space(attid);
529 atype = H5Aget_type(attid);
531 t_class = H5Tget_class(atype);
532 if(t_class != H5T_STRING)
534 size = H5Tget_size(atype);
537 text = (
char*)malloc(1+(
size_t)size);
540 if((ntype = H5Tget_native_type(atype, H5T_DIR_DEFAULT)) < 0)
542 if((H5Aread(attid, ntype, text)) < 0)
545 text[(size_t)size] =
'\0';
547 if((retval = NC4_get_provenance(h5, text, &globalpropinfo)))
551 if(text != NULL) free(text);
553 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
554 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
555 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
556 if(ntype > 0 && H5Tclose(ntype) < 0) retval =
NC_EHDFERR;
560 LOG((0,
"Invalid _NCProperties attribute"));
567 NC4_write_ncproperties(NC_FILE_INFO_T* h5)
570 hid_t hdf5grpid = -1;
581 hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
583 if(H5Aexists(hdf5grpid,NCPROPS) > 0)
587 if((retval = NC4_buildpropinfo(&h5->provenance->propattr,&text)))
591 if ((atype = H5Tcopy(H5T_C_S1)) < 0)
593 if (H5Tset_strpad(atype, H5T_STR_NULLTERM) < 0)
595 if(H5Tset_cset(atype, H5T_CSET_ASCII) < 0)
601 if(H5Tset_size(atype, len) < 0)
603 if((aspace = H5Screate(H5S_SCALAR)) < 0)
605 if ((attid = H5Acreate(hdf5grpid, NCPROPS, atype, aspace, H5P_DEFAULT)) < 0)
607 if (H5Awrite(attid, atype, text) < 0)
611 if(text != NULL) free(text);
613 if(attid > 0 && H5Aclose(attid) < 0) retval =
NC_EHDFERR;
614 if(aspace > 0 && H5Sclose(aspace) < 0) retval =
NC_EHDFERR;
615 if(atype > 0 && H5Tclose(atype) < 0) retval =
NC_EHDFERR;
626 LOG((0,
"Invalid _NCProperties attribute"));
636 ncprintpropinfo(
struct NCPROPINFO* info)
639 fprintf(stderr,
"[%p] version=%d\n",info,info->version);
640 for(i=0;i<nclistlength(info->properties);i+=2) {
641 char* name = nclistget(info->properties,i);
642 char* value = nclistget(info->properties,i+1);
643 fprintf(stderr,
"\t[%d] name=|%s| value=|%s|\n",i,name,value);
648 ncprintprovenance(
struct NCPROVENANCE* prov)
650 fprintf(stderr,
"[%p] superblockversion=%d\n",prov,prov->superblockversion);
651 ncprintpropinfo(&prov->propattr);
struct NCPROPINFO globalpropinfo
Global property info.
#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_EPERM
Write to read only.
#define NC_NOERR
No Error.