summaryrefslogtreecommitdiffstats
path: root/src/H5Groot.c
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2009-04-08 22:16:45 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2009-04-08 22:16:45 (GMT)
commitef77500b284962ce87126ed86186019431bcf119 (patch)
tree8d6339aa3d36938cc8205ad71e2426899f1f72f7 /src/H5Groot.c
parent6f925167762871f0f1a416afdac25b5f1341aef4 (diff)
downloadhdf5-ef77500b284962ce87126ed86186019431bcf119.zip
hdf5-ef77500b284962ce87126ed86186019431bcf119.tar.gz
hdf5-ef77500b284962ce87126ed86186019431bcf119.tar.bz2
[svn-r16712] Purpose: Fix bug 1423
Description: Versions of the library between 1.3.0 and 1.6.3 have a bug which prevents them from opening any file that does not have the root group's symbol table information cached in the root group's entry in the superblock. Prior to 1.8 this was not an issue as this information was always cached. However, 1.8.0 stopped writing this information (which is not required by the file format specification), and these older versions can therefore not read files created or last written by versions 1.8.0 to 1.8.2. This fix modifies the library to once again add this information to the superblock (when using the old file format). Tested: jam, linew, smirom (h5committest)
Diffstat (limited to 'src/H5Groot.c')
-rw-r--r--src/H5Groot.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/src/H5Groot.c b/src/H5Groot.c
new file mode 100644
index 0000000..4c7c357
--- /dev/null
+++ b/src/H5Groot.c
@@ -0,0 +1,344 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /*-------------------------------------------------------------------------
+ *
+ * Created: H5Gobj.c
+ * Apr 8 2009
+ * Neil Fortner <nfortne2@hdfgroup.org>
+ *
+ * Purpose: Functions for operating on the root group.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5Gpkg.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property Lists */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_rootof
+ *
+ * Purpose: Return a pointer to the root group of the file. If the file
+ * is part of a virtual file then the root group of the virtual
+ * file is returned.
+ *
+ * Return: Success: Ptr to the root group of the file. Do not
+ * free the pointer -- it points directly into
+ * the file struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 13, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_t *
+H5G_rootof(H5F_t *f)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof)
+
+ while(f->parent)
+ f = f->parent;
+
+ FUNC_LEAVE_NOAPI(f->shared->root_grp)
+} /* end H5G_rootof() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_root_ent_decode
+ *
+ * Purpose: Decodes the root group symbol table entry into the file
+ * structure, and updates the root group address in the file
+ * structure.
+ *
+ * Return: Success: Non-negative with *pp pointing to the first byte
+ * following the symbol table entry.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Sep 26 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_root_ent_decode(H5F_t *f, const uint8_t **pp)
+{
+ const uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_root_ent_decode, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(pp);
+
+ /* Allocate space for the root group symbol table entry */
+ HDassert(!f->shared->root_ent);
+ if(NULL == (f->shared->root_ent = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+
+ /* decode the root group symbol table entry */
+ if(H5G_ent_decode_vec(f, pp, f->shared->root_ent, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry")
+
+ /* Set the root group address to the correct value */
+ f->shared->root_addr = f->shared->root_ent->header;
+
+ /* Set decode pointer */
+ *pp = p_ret;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_root_ent_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_root_ent_encode
+ *
+ * Purpose: Encodes the root group symbol table entry into the buffer
+ * pointed to by *pp.
+ *
+ * Return: Success: Non-negative, with *pp pointing to the first byte
+ * after the symbol table entry.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Sep 26 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_root_ent_encode(H5F_t *f, uint8_t **pp)
+{
+ uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_root_ent_encode, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->root_ent);
+ HDassert(pp);
+
+ /* Encode entry */
+ if(H5G_ent_encode_vec(f, pp, f->shared->root_ent, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode symbol table entry")
+
+ /* Set encode pointer */
+ *pp = p_ret;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_root_ent_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_mkroot
+ *
+ * Purpose: Creates a root group in an empty file and opens it. If a
+ * root group is already open then this function immediately
+ * returns. If ENT is non-null then it's the symbol table
+ * entry for an existing group which will be opened as the root
+ * group. Otherwise a new root group is created and then
+ * opened.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 11 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_mkroot(H5F_t *f, hid_t dxpl_id, hbool_t create_root)
+{
+ H5G_loc_t root_loc; /* Root location information */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_mkroot, FAIL)
+
+ /* check args */
+ HDassert(f);
+
+ /* Check if the root group is already initialized */
+ if(f->shared->root_grp)
+ HGOTO_DONE(SUCCEED)
+
+ /* Create information needed for group nodes */
+ if(H5G_node_init(f) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group node info")
+
+ /*
+ * Create the group pointer
+ */
+ if(NULL == (f->shared->root_grp = H5FL_CALLOC(H5G_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (f->shared->root_grp->shared = H5FL_CALLOC(H5G_shared_t))) {
+ (void)H5FL_FREE(H5G_t, f->shared->root_grp);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+
+ /* Initialize the root_loc structure to point to fields in the newly created
+ * f->shared->root_grp structure */
+ root_loc.oloc = &(f->shared->root_grp->oloc);
+ root_loc.path = &(f->shared->root_grp->path);
+ H5G_loc_reset(&root_loc);
+
+ /*
+ * If there is no root object then create one. The root group always starts
+ * with a hard link count of one since it's pointed to by the superblock.
+ */
+ if(create_root) {
+ H5P_genplist_t *fc_plist; /* File creation property list */
+ H5O_ginfo_t ginfo; /* Group info parameters */
+ H5O_linfo_t linfo; /* Link info parameters */
+ unsigned super_vers; /* Superblock version */
+
+ /* Get the file creation property list */
+ /* (Which is a sub-class of the group creation property class) */
+ if(NULL == (fc_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get the group info property */
+ if(H5P_get(fc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info")
+
+ /* Get the link info property */
+ if(H5P_get(fc_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get link info")
+
+ /* Get the superblock version */
+ if(H5P_get(fc_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get superblock version")
+
+ /* Create root group */
+ if(H5G_obj_create(f, dxpl_id, &ginfo, &linfo, f->shared->fcpl_id, root_loc.oloc/*out*/) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry")
+ if(1 != H5O_link(root_loc.oloc, 1, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "internal error (wrong link count)")
+
+ /* Create the root group symbol table entry */
+ HDassert(!f->shared->root_ent);
+ if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ /* Allocate space for the root group symbol table entry */
+ if(NULL == (f->shared->root_ent = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+
+ /* Initialize the root group symbol table entry */
+ f->shared->root_ent->dirty = TRUE;
+ f->shared->root_ent->type = H5G_NOTHING_CACHED; /* We will cache the stab later */
+ f->shared->root_ent->name_off = 0; /* No name (yet) */
+ f->shared->root_ent->header = root_loc.oloc->addr;
+ f->shared->root_ent->file = root_loc.oloc->file;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Create root group object location from f */
+ root_loc.oloc->addr = f->shared->root_addr;
+ root_loc.oloc->file = f;
+
+ /*
+ * Open the root object as a group.
+ */
+ if(H5O_open(root_loc.oloc) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group")
+
+#ifndef H5_STRICT_FORMAT_CHECKS
+ /* If symbol table information is cached, check if we should replace the
+ * symbol table message with the cached symbol table information */
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent
+ && (f->shared->root_ent->type == H5G_CACHED_STAB)) {
+ H5O_stab_t cached_stab;
+
+ /* Retrieve the cached symbol table information */
+ cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr;
+ cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr;
+
+ /* Check if the symbol table message is valid, and replace with the
+ * cached symbol table if necessary */
+ if(H5G_stab_valid(root_loc.oloc, dxpl_id, &cached_stab) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table")
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+ } /* end else */
+
+ /* Cache the root group's symbol table information in the root group symbol
+ * table entry. It will have been allocated by now if it needs to be
+ * present, so we don't need to check the superblock version. We do this if
+ * we have write access, the root entry has been allocated (i.e.
+ * super_vers < 2) and the stab info is not already cached. */
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent
+ && f->shared->root_ent->type != H5G_CACHED_STAB) {
+ htri_t stab_exists; /* Whether the symbol table exists */
+ H5O_stab_t stab; /* Symbol table */
+
+ /* Check if the stab message exists. It's possible for the root group
+ * to use the latest version while the superblock is an old version. */
+ if((stab_exists = H5O_msg_exists(root_loc.oloc, H5O_STAB_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check if symbol table message exists")
+
+ if(stab_exists) {
+ /* Read the root group's symbol table message */
+ if(NULL == H5O_msg_read(root_loc.oloc, H5O_STAB_ID, &stab, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message")
+
+ /* Update the root group symbol table entry */
+ f->shared->root_ent->type = H5G_CACHED_STAB;
+ f->shared->root_ent->cache.stab.btree_addr = stab.btree_addr;
+ f->shared->root_ent->cache.stab.heap_addr = stab.heap_addr;
+ } /* end if */
+ } /* end if */
+
+ /* Create the path names for the root group's entry */
+ H5G_name_init(root_loc.path, "/");
+
+ f->shared->root_grp->shared->fo_count = 1;
+ /* The only other open object should be the superblock extension, if it
+ * exists. Don't count either the superblock extension or the root group
+ * in the number of open objects in the file.
+ */
+ HDassert((1 == f->nopen_objs) ||
+ (2 == f->nopen_objs && HADDR_UNDEF != f->shared->extension_addr));
+ f->nopen_objs--;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_mkroot() */
+