diff --git a/parcel.h b/parcel.h index 2ada709..65320c0 100644 --- a/parcel.h +++ b/parcel.h @@ -2329,26 +2329,31 @@ pmd_status pmd_open_series(const char *filename, pmd_series **series_out, pmd_ac } else { // Open the HDF5 file file_id = H5Fopen(maybe_padded_iter_filename, H5F_ACC_RDONLY, H5P_DEFAULT); - if (file_id >= 0) { - /* Read metadata from the opened file */ - status = read_series_metadata_from_file(file_id, series, filename); - if (status != PMD_SUCCESS) { - goto cleanup; - } - maybe_padded_file = maybe_padded_iter_filename; + if (file_id < 0) { + pmd_log(PMD_LOG_ERROR, "Failed to open '%s' (matched pattern '%s') as HDF5", + maybe_padded_iter_filename, filename); + status = PMD_ERROR_HDF5; + goto cleanup; + } - /* A %T filename pattern is only valid for file-based series */ - if (series->iteration_encoding != PMD_FILE_BASED) { - pmd_log(PMD_LOG_ERROR, "File '%s' matched pattern '%s' but is not a fileBased series", - maybe_padded_iter_filename, filename); - status = PMD_ERROR_FILE_FORMAT; - goto cleanup; - } + /* Read metadata from the opened file */ + status = read_series_metadata_from_file(file_id, series, filename); + if (status != PMD_SUCCESS) { + goto cleanup; + } + maybe_padded_file = maybe_padded_iter_filename; - /* Close file since we will not store for file-based mode */ - H5Fclose(file_id); - file_id = -1; + /* A %T filename pattern is only valid for file-based series */ + if (series->iteration_encoding != PMD_FILE_BASED) { + pmd_log(PMD_LOG_ERROR, "File '%s' matched pattern '%s' but is not a fileBased series", + maybe_padded_iter_filename, filename); + status = PMD_ERROR_FILE_FORMAT; + goto cleanup; } + + /* Close file since we will not store for file-based mode */ + H5Fclose(file_id); + file_id = -1; } /* Set directory from pattern if not already set */ diff --git a/tests/test_write.c b/tests/test_write.c index 7ab21f5..3b3455a 100644 --- a/tests/test_write.c +++ b/tests/test_write.c @@ -1009,6 +1009,29 @@ void test_invalid_pattern_ambiguous(void) { TEST_ASSERT_NOT_EQUAL(PMD_SUCCESS, result); } +/** + * Test: %T filename pattern that matches a file HDF5 cannot open fails + */ +void test_pattern_open_invalid_hdf5_fails(void) { + pmd_series *series; + pmd_status result; + + /* Create a file whose name matches bad_%T.h5 but is not HDF5 */ + FILE *bad_file = fopen(TEST_TEMP_DIR "/bad_0.h5", "wb"); + TEST_ASSERT_NOT_NULL(bad_file); + TEST_ASSERT_TRUE(fputs("not an hdf5 file\n", bad_file) >= 0); + TEST_ASSERT_EQUAL_INT(0, fclose(bad_file)); + + /* Read-only must be checked first: RDWR writes root attributes during open */ + result = pmd_open_series(TEST_TEMP_DIR "/bad_%T.h5", &series, PMD_RDONLY); + TEST_ASSERT_EQUAL_INT(PMD_ERROR_HDF5, result); + TEST_ASSERT_NULL(series); + + result = pmd_open_series(TEST_TEMP_DIR "/bad_%T.h5", &series, PMD_RDWR); + TEST_ASSERT_EQUAL_INT(PMD_ERROR_HDF5, result); + TEST_ASSERT_NULL(series); +} + /** * Test: %T filename pattern that matches a group-based file fails */ @@ -2730,6 +2753,7 @@ int main(void) { RUN_TEST(test_write_nonconsecutive_iterations_file_based); RUN_TEST(test_write_fails_no_parent_directory); RUN_TEST(test_invalid_pattern_ambiguous); + RUN_TEST(test_pattern_open_invalid_hdf5_fails); RUN_TEST(test_pattern_matching_group_based_file_fails); RUN_TEST(test_valid_filebased_patterns); RUN_TEST(test_truncate_deletes_existing_files);