ECC-727: handle all versions of HDF5 Super Block

This commit is contained in:
Shahram Najm 2018-07-31 17:40:34 +01:00
commit 470cc72243
2 changed files with 149 additions and 62 deletions

View File

@ -1,11 +1,50 @@
# http://www.hdfgroup.org/HDF5/doc/H5.format.html#Superblock
constant identifier="HDF5";
ascii[8] signature : dump;
uint8 versionNumberOfSuperblock : dump;
if(versionNumberOfSuperblock == 2) {
if (versionNumberOfSuperblock == 0 || versionNumberOfSuperblock == 1)
{
uint8 versionNumOfFilesFreeSpaceStorage : dump;
uint8 versionNumOfRootGroupSymbolTableEntry : dump;
uint8 reserved1;
uint8 versionNumOfSharedHeaderMessageFormat: dump;
uint8 sizeOfOffsets : dump;
uint8 sizeOfLength : dump;
uint8 reserved2;
#uint32_little_endian groupLeafAndInternalNodeK : dump;
#uint32_little_endian fileConsistencyFlags : dump;
#unsigned[4] groupLeafAndInternalNodeK : dump;
unsigned[2] groupLeafNodeK : dump;
unsigned[2] groupInternalNodeK : dump;
unsigned[4] fileConsistencyFlags : dump;
if (versionNumberOfSuperblock == 1) {
uint16 indexedStorageInternalNodeK : dump;
uint16 reserved3;
}
if(sizeOfOffsets == 8) {
uint64_little_endian baseAddress : dump;
uint64_little_endian addressOfFileFreeSpaceInfo : dump;
uint64_little_endian endOfFileAddress : dump;
uint64_little_endian driverInformationBlockAddress : dump;
uint64_little_endian rootGroupSymbolTableEntry: dump;
}
if(sizeOfOffsets == 4) {
uint32_little_endian baseAddress : dump;
uint32_little_endian addressOfFileFreeSpaceInfo : dump;
uint32_little_endian endOfFileAddress : dump;
uint32_little_endian driverInformationBlockAddress : dump;
uint32_little_endian rootGroupSymbolTableEntry: dump;
}
}
if (versionNumberOfSuperblock == 2 || versionNumberOfSuperblock == 3)
{
uint8 sizeOfOffsets : dump;
uint8 sizeOfLength : dump;
uint8 fileConsistencyFlags : dump;
@ -25,5 +64,4 @@ if(versionNumberOfSuperblock == 2) {
}
#ascii[4] superblockChecksum;
}

View File

@ -495,7 +495,7 @@ static int read_HDF5_offset(reader *r, int length, unsigned long* v, unsigned ch
static int read_HDF5(reader *r)
{
/* See: http://www.hdfgroup.org/HDF5/doc/H5.format.html#Superblock */
unsigned char tmp[36]; /* Should be enough */
unsigned char tmp[49]; /* Should be enough */
unsigned char buf[4];
unsigned char version_of_superblock, size_of_offsets, size_of_lengths, consistency_flags;
@ -530,18 +530,13 @@ static int read_HDF5(reader *r)
tmp[i++] = version_of_superblock;
if(version_of_superblock != 2) {
grib_context_log(c, GRIB_LOG_ERROR,"read_HDF5: invalid version_of_superblock: %ld, only version 2 is supported", (long)version_of_superblock);
return GRIB_NOT_IMPLEMENTED;
}
if (version_of_superblock == 2 || version_of_superblock == 3) {
if( (r->read(r->read_data, &size_of_offsets, 1, &err) != 1) || err) {
return err;
}
tmp[i++] = size_of_offsets;
if(size_of_offsets > 8) {
grib_context_log(c, GRIB_LOG_ERROR,"read_HDF5: invalid size_of_offsets: %ld, only <= 8 is supported", (long)size_of_offsets);
return GRIB_NOT_IMPLEMENTED;
@ -573,6 +568,60 @@ static int read_HDF5(reader *r)
if(err) {
return err;
}
} else if (version_of_superblock == 0 || version_of_superblock == 1) {
char skip[4];
unsigned long file_free_space_info;
unsigned char version_of_file_free_space, version_of_root_group_symbol_table, version_number_shared_header, ch;
if( (r->read(r->read_data, &version_of_file_free_space, 1, &err) != 1) || err) return err;
tmp[i++] = version_of_file_free_space;
if( (r->read(r->read_data, &version_of_root_group_symbol_table, 1, &err) != 1) || err) return err;
tmp[i++] = version_of_root_group_symbol_table;
if( (r->read(r->read_data, &ch, 1, &err) != 1) || err) return err; /* reserved */
tmp[i++] = ch;
if( (r->read(r->read_data, &version_number_shared_header, 1, &err) != 1) || err) return err;
tmp[i++] = version_number_shared_header;
if( (r->read(r->read_data, &size_of_offsets, 1, &err) != 1) || err) return err;
tmp[i++] = size_of_offsets;
if (size_of_offsets > 8) {
grib_context_log(c, GRIB_LOG_ERROR,"read_HDF5: invalid size_of_offsets: %ld, only <= 8 is supported", (long)size_of_offsets);
return GRIB_NOT_IMPLEMENTED;
}
if( (r->read(r->read_data, &size_of_lengths, 1, &err) != 1) || err) return err;
tmp[i++] = size_of_lengths;
if( (r->read(r->read_data, &ch, 1, &err) != 1) || err) return err; /*reserved*/
tmp[i++] = ch;
if( (r->read(r->read_data, &skip, 4, &err) != 4) || err) return err; /* Group Leaf/Internal Node K: 4 bytes */
tmp[i++] = skip[0]; tmp[i++] = skip[1]; tmp[i++] = skip[2]; tmp[i++] = skip[3];
if( (r->read(r->read_data, &skip, 4, &err) != 4) || err) return err; /* consistency_flags: 4 bytes */
tmp[i++] = skip[0]; tmp[i++] = skip[1]; tmp[i++] = skip[2]; tmp[i++] = skip[3];
if (version_of_superblock == 1) {
/* Indexed storage internal node K and reserved: only in version 1 of superblock */
if( (r->read(r->read_data, &skip, 4, &err) != 4) || err) return err;
tmp[i++] = skip[0]; tmp[i++] = skip[1]; tmp[i++] = skip[2]; tmp[i++] = skip[3];
}
err = read_HDF5_offset(r, size_of_offsets, &base_address, tmp, &i);
if (err) return err;
err = read_HDF5_offset(r, size_of_offsets, &file_free_space_info, tmp, &i);
if (err) return err;
err = read_HDF5_offset(r, size_of_offsets, &end_of_file_address, tmp, &i);
if (err) return err;
} else {
grib_context_log(c, GRIB_LOG_ERROR,"read_HDF5: invalid version of superblock: %ld", (long)version_of_superblock);
return GRIB_NOT_IMPLEMENTED;
}
Assert(i <= sizeof(tmp));
return read_the_rest(r, end_of_file_address, tmp, i, 0);