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.