Beispiel #1
0
/*-------------------------------------------------------------------------
 * Function:	H5F__cache_superblock_deserialize
 *
 * Purpose:	Loads an object from the disk.
 *
 * Return:	Success:	Pointer to new object
 *		Failure:	NULL
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		July 18 2013
 *
 *-------------------------------------------------------------------------
 */
static void *
H5F__cache_superblock_deserialize(const void *_image, size_t len, void *_udata,
    hbool_t H5_ATTR_UNUSED *dirty)
{
    H5F_super_t         *sblock = NULL; /* File's superblock */
    H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
    const uint8_t	*image = (const uint8_t *)_image;       /* Pointer into raw data buffer */
    size_t              variable_size;  /* Variable size of superblock */
    unsigned            super_vers;     /* Superblock version */
    uint8_t             sizeof_addr;    /* Size of offsets in the file (in bytes) */
    uint8_t             sizeof_size;    /* Size of lengths in the file (in bytes) */
    H5F_super_t         *ret_value = NULL;      /* Return value */

    FUNC_ENTER_STATIC

    /* Check arguments */
    HDassert(image);
    HDassert(udata);
    HDassert(udata->f);

    /* Allocate space for the superblock */
    if(NULL == (sblock = H5FL_CALLOC(H5F_super_t)))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    image += H5F_SIGNATURE_LEN;

    /* Superblock version */
    super_vers = *image++;
    if(super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock version number")

    /* Record the superblock version */
    sblock->super_vers = super_vers;

    /* Sanity check */
    HDassert(((size_t)(image - (const uint8_t *)_image)) == H5F_SUPERBLOCK_FIXED_SIZE);
    HDassert(len >= H5F_SUPERBLOCK_FIXED_SIZE + 6);

    /* Determine the size of addresses & size of offsets, for computing the
     * variable-sized portion of the superblock.
     */
    if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
        sizeof_addr = image[4];
        sizeof_size = image[5];
    } /* end if */
    else {
        sizeof_addr = image[0];
        sizeof_size = image[1];
    } /* end else */
    if(sizeof_addr != 2 && sizeof_addr != 4 &&
            sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
    if(sizeof_size != 2 && sizeof_size != 4 &&
            sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
    sblock->sizeof_addr = sizeof_addr;
    sblock->sizeof_size = sizeof_size;

    /* Determine the size of the variable-length part of the superblock */
    variable_size = (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, sizeof_addr, sizeof_size);
    HDassert(variable_size > 0);

    HDassert(len == (H5F_SUPERBLOCK_FIXED_SIZE + variable_size));

    /* Check for older version of superblock format */
    if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
	uint32_t    status_flags;	    /* File status flags	   */
	unsigned    sym_leaf_k;         /* Symbol table leaf node's 'K' value */
	unsigned    snode_btree_k;      /* B-tree symbol table internal node 'K' value */
	unsigned    chunk_btree_k;      /* B-tree chunk internal node 'K' value */

	/* Freespace version (hard-wired) */
	if(HDF5_FREESPACE_VERSION != *image++)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number")

	/* Root group version number (hard-wired) */
	if(HDF5_OBJECTDIR_VERSION != *image++)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number")

	/* Skip over reserved byte */
	image++;

	/* Shared header version number (hard-wired) */
	if(HDF5_SHAREDHEADER_VERSION != *image++)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number")

	/* Size of file addresses */
	sizeof_addr = *image++;
	if(sizeof_addr != 2 && sizeof_addr != 4 &&
		sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
	sblock->sizeof_addr = sizeof_addr;
	udata->f->shared->sizeof_addr = sizeof_addr;  /* Keep a local copy also */

	/* Size of file sizes */
	sizeof_size = *image++;
	if(sizeof_size != 2 && sizeof_size != 4 &&
		sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
	sblock->sizeof_size = sizeof_size;
	udata->f->shared->sizeof_size = sizeof_size;  /* Keep a local copy also */

	/* Skip over reserved byte */
	image++;

	/* Various B-tree sizes */
	UINT16DECODE(image, sym_leaf_k);
	if(sym_leaf_k == 0)
	    HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank")
        udata->sym_leaf_k = sym_leaf_k;    /* Keep a local copy also */

        /* Need 'get' call to set other array values */
        UINT16DECODE(image, snode_btree_k);
        if(snode_btree_k == 0)
	    HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes")
	udata->btree_k[H5B_SNODE_ID] = snode_btree_k;

	/*
         * Delay setting the value in the property list until we've checked
         * for the indexed storage B-tree internal 'K' value later.
         */

        /* File status flags (not really used yet) */
        UINT32DECODE(image, status_flags);
        HDassert(status_flags <= 255);
        sblock->status_flags = (uint8_t)status_flags;
        if(sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
	    HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")

	/*
         * If the superblock version # is greater than 0, read in the indexed
         * storage B-tree internal 'K' value
         */
        if(super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
	    UINT16DECODE(image, chunk_btree_k);

	    /* Reserved bytes are present only in version 1 */
	    if(super_vers == HDF5_SUPERBLOCK_VERSION_1)
		image += 2;   /* reserved */
	} /* end if */
	else
	    chunk_btree_k = HDF5_BTREE_CHUNK_IK_DEF;
	udata->btree_k[H5B_CHUNK_ID] = chunk_btree_k;

	/* Remainder of "variable-sized" portion of superblock */
	H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr/*out*/);
	H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr/*out*/);
	H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof/*out*/);
	H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->driver_addr/*out*/);

	/* Allocate space for the root group symbol table entry */
	HDassert(!sblock->root_ent);
	if(NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t))))
	    HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for root group symbol table entry")

	/* decode the root group symbol table entry */
	if(H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent) < 0)
	    HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry")

	/* Set the root group address to the correct value */
	sblock->root_addr = sblock->root_ent->header;

	/* This step is for h5repart tool only. If user wants to change file driver
         *  from family to sec2 while using h5repart, set the driver address to
         *  undefined to let the library ignore the family driver information saved
         *  in the superblock.
         */
	if(udata->ignore_drvrinfo && H5F_addr_defined(sblock->driver_addr)) {
	    /* Eliminate the driver info */
	    sblock->driver_addr = HADDR_UNDEF;
            udata->drvrinfo_removed = TRUE;
	} /* end if */

	/* NOTE: Driver info block is decoded separately, later */

    } /* end if */
/*-------------------------------------------------------------------------
 * Function:    H5F_sblock_load
 *
 * Purpose:     Loads the superblock from the file, and deserializes
 *              its information into the H5F_super_t structure.
 *
 * Return:      Success:        SUCCEED
 *              Failure:        NULL
 *
 * Programmer:  Mike McGreevy
 *              [email protected]
 *              April 8, 2009
 *
 *-------------------------------------------------------------------------
 */
static H5F_super_t *
H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, void *_udata)
{
    H5F_super_t        *sblock = NULL;      /* File's superblock */
    haddr_t             base_addr = HADDR_UNDEF;        /* Base address of file */
    uint8_t             sbuf[H5F_MAX_SUPERBLOCK_SIZE];     /* Buffer for superblock */
    H5P_genplist_t     *dxpl;               /* DXPL object */
    H5P_genplist_t     *c_plist;            /* File creation property list  */
    H5F_file_t         *shared;             /* shared part of `file'        */
    H5FD_t             *lf;                 /* file driver part of `shared' */
    haddr_t             stored_eoa;         /*relative end-of-addr in file  */
    haddr_t             eof;                /*end of file address           */
    uint8_t             sizeof_addr;        /* Size of offsets in the file (in bytes) */
    uint8_t             sizeof_size;        /* Size of lengths in the file (in bytes) */
    const size_t        fixed_size = H5F_SUPERBLOCK_FIXED_SIZE; /*fixed sizeof superblock   */
    size_t              variable_size;      /*variable sizeof superblock    */
    uint8_t            *p;                  /* Temporary pointer into encoding buffer */
    unsigned            super_vers;         /* Superblock version          */
    hbool_t            *dirtied = (hbool_t *)_udata;  /* Set up dirtied out value */
    H5F_super_t        *ret_value;          /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* check arguments */
    HDassert(f);
    HDassert(H5F_addr_eq(addr, 0));
    HDassert(dirtied);

    /* Short cuts */
    shared = f->shared;
    lf = shared->lf;

    /* Get the shared file creation property list */
    if(NULL == (c_plist = (H5P_genplist_t *)H5I_object(shared->fcpl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get property list")

    /* Get the base address for the file in the VFD */
    if(HADDR_UNDEF == (base_addr = H5FD_get_base_addr(lf)))
        HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "failed to get base address for file driver")

    /* Allocate space for the superblock */
    if(NULL == (sblock = H5FL_CALLOC(H5F_super_t)))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Get the DXPL plist object for DXPL ID */
    if(NULL == (dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get property list")

    /* Read fixed-size portion of the superblock */
    p = sbuf;
    H5_CHECK_OVERFLOW(fixed_size, size_t, haddr_t);
    if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)fixed_size) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
    if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, (haddr_t)0, fixed_size, p) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")

    /* Skip over signature (already checked when locating the superblock) */
    p += H5F_SIGNATURE_LEN;

    /* Superblock version */
    super_vers = *p++;
    if(super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock version number")
    if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set superblock version")

    /* Record the superblock version */
    sblock->super_vers = super_vers;

    /* Sanity check */
    HDassert(((size_t)(p - sbuf)) == fixed_size);

    /* Determine the size of the variable-length part of the superblock */
    variable_size = (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, f);
    HDassert(variable_size > 0);
    HDassert(fixed_size + variable_size <= sizeof(sbuf));

    /* Read in variable-sized portion of superblock */
    if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (haddr_t)(fixed_size + variable_size)) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
    if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, (haddr_t)fixed_size, variable_size, p) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read superblock")

    /* Check for older version of superblock format */
    if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
        uint32_t	status_flags;	    /* File status flags	   */
        unsigned        btree_k[H5B_NUM_BTREE_ID];  /* B-tree internal node 'K' values */
        unsigned        sym_leaf_k;         /* Symbol table leaf node's 'K' value */

        /* Freespace version (hard-wired) */
        if(HDF5_FREESPACE_VERSION != *p++)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number")

        /* Root group version number (hard-wired) */
        if(HDF5_OBJECTDIR_VERSION != *p++)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number")

        /* Skip over reserved byte */
        p++;

        /* Shared header version number (hard-wired) */
        if(HDF5_SHAREDHEADER_VERSION != *p++)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number")

        /* Size of file addresses */
        sizeof_addr = *p++;
        if(sizeof_addr != 2 && sizeof_addr != 4 &&
                sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address")
        if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sizeof_addr) < 0)
            HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address")
        shared->sizeof_addr = sizeof_addr;  /* Keep a local copy also */

        /* Size of file sizes */
        sizeof_size = *p++;
        if(sizeof_size != 2 && sizeof_size != 4 &&
                sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size")
        if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0)
            HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size")
        shared->sizeof_size = sizeof_size;  /* Keep a local copy also */

        /* Skip over reserved byte */
        p++;

        /* Various B-tree sizes */
        UINT16DECODE(p, sym_leaf_k);
        if(sym_leaf_k == 0)
            HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank")
        if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0)
            HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes")
        sblock->sym_leaf_k = sym_leaf_k;    /* Keep a local copy also */

        /* Need 'get' call to set other array values */
        if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
            HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes")
        UINT16DECODE(p, btree_k[H5B_SNODE_ID]);
        if(btree_k[H5B_SNODE_ID] == 0)
            HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes")
        /*
         * Delay setting the value in the property list until we've checked
         * for the indexed storage B-tree internal 'K' value later.
         */

        /* File status flags (not really used yet) */
        UINT32DECODE(p, status_flags);
        HDassert(status_flags <= 255);
        sblock->status_flags = (uint8_t)status_flags;
        if(sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock")

        /*
         * If the superblock version # is greater than 0, read in the indexed
         * storage B-tree internal 'K' value
         */
        if(super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
            UINT16DECODE(p, btree_k[H5B_CHUNK_ID]);
            /* Reserved bytes are present only in version 1 */
            if(super_vers == HDF5_SUPERBLOCK_VERSION_1)
                p += 2;   /* reserved */
        } /* end if */
        else
            btree_k[H5B_CHUNK_ID] = HDF5_BTREE_CHUNK_IK_DEF;

        /* Set the B-tree internal node values, etc */
        if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
            HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for btree internal nodes")
        HDmemcpy(sblock->btree_k, btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID);    /* Keep a local copy also */

        /* Remainder of "variable-sized" portion of superblock */
        H5F_addr_decode(f, (const uint8_t **)&p, &sblock->base_addr/*out*/);
        H5F_addr_decode(f, (const uint8_t **)&p, &sblock->ext_addr/*out*/);
        H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
        H5F_addr_decode(f, (const uint8_t **)&p, &sblock->driver_addr/*out*/);

        /* Allocate space for the root group symbol table entry */
        HDassert(!sblock->root_ent);
        if(NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t))))
            HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for root group symbol table entry")

        /* decode the root group symbol table entry */
        if(H5G_ent_decode(f, (const uint8_t **)&p, sblock->root_ent) < 0)
            HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry")

        /* Set the root group address to the correct value */
        sblock->root_addr = sblock->root_ent->header;

        /*
         * Check if superblock address is different from base address and
         * adjust base address and "end of address" address if so.
         */
        if(!H5F_addr_eq(base_addr, sblock->base_addr)) {
            /* Check if the superblock moved earlier in the file */
            if(H5F_addr_lt(base_addr, sblock->base_addr))
                stored_eoa -= (sblock->base_addr - base_addr);
            else
                /* The superblock moved later in the file */
                stored_eoa += (base_addr - sblock->base_addr);

            /* Adjust base address for offsets of the HDF5 data in the file */
            sblock->base_addr = base_addr;

            /* Set the base address for the file in the VFD now */
            if(H5FD_set_base_addr(lf, sblock->base_addr) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "failed to set base address for file driver")

            /* Indicate that the superblock should be marked dirty */
            *dirtied = TRUE;
        } /* end if */

        /* This step is for h5repart tool only. If user wants to change file driver
         *  from family to sec2 while using h5repart, set the driver address to
         *  undefined to let the library ignore the family driver information saved
         *  in the superblock.
         */
        if(H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) {
            /* Eliminate the driver info */
            sblock->driver_addr = HADDR_UNDEF;

            /* Indicate that the superblock should be marked dirty */
            *dirtied = TRUE;
        } /* end if */

        /* Decode the optional driver information block */
        if(H5F_addr_defined(sblock->driver_addr)) {
            uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE];     /* Buffer for driver info block */
            char drv_name[9];       /* Name of driver */
            unsigned drv_vers;      /* Version of driver info block */
            size_t drv_variable_size; /* Size of variable-length portion of driver info block, in bytes */

            /* Read in fixed-sized portion of driver info block */
            p = dbuf;
            if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
            if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, sblock->driver_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read driver information block")

            /* Version number */
            drv_vers = *p++;
            if(drv_vers != HDF5_DRIVERINFO_VERSION_0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "bad driver information block version number")

            p += 3; /* reserved bytes */

            /* Driver info size */
            UINT32DECODE(p, drv_variable_size);

            /* Sanity check */
            HDassert(H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size <= sizeof(dbuf));

            /* Driver name and/or version */
            HDstrncpy(drv_name, (const char *)p, (size_t)8);
            drv_name[8] = '\0';
            p += 8; /* advance past name/version */

            /* Check if driver matches driver information saved. Unfortunately, we can't push this
             * function to each specific driver because we're checking if the driver is correct.
             */
            if(!HDstrncmp(drv_name, "NCSAfami", (size_t)8) && HDstrcmp(lf->cls->name, "family"))
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "family driver should be used")
            if(!HDstrncmp(drv_name, "NCSAmult", (size_t)8) && HDstrcmp(lf->cls->name, "multi"))
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "multi driver should be used")

            /* Read in variable-sized portion of driver info block */
            if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "set end of space allocation request failed")
            if(H5FD_read(lf, dxpl, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read file driver information")

            /* Decode driver information */
            if(H5FD_sb_decode(lf, drv_name, p) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to decode driver information")
        } /* end if */
Beispiel #3
0
/*-------------------------------------------------------------------------
 * Function:    H5F_read_superblock
 *
 * Purpose:     Reads the superblock from the file or from the BUF. If
 *              ADDR is a valid address, then it reads it from the file.
 *              If not, then BUF must be non-NULL for it to read from the
 *              BUF.
 *
 * Return:      Success:        SUCCEED
 *              Failure:        FAIL
 *
 * Programmer:  Bill Wendling
 *              [email protected]
 *              Sept 12, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent)
{
    haddr_t             stored_eoa;         /*relative end-of-addr in file  */
    haddr_t             eof;                /*end of file address           */
    uint8_t            *q;                  /*ptr into temp I/O buffer      */
    size_t              sizeof_addr = 0;
    size_t              sizeof_size = 0;
    const size_t        fixed_size = 24;    /*fixed sizeof superblock       */
    unsigned            sym_leaf_k = 0;
    size_t              variable_size;      /*variable sizeof superblock    */
    unsigned            btree_k[H5B_NUM_BTREE_ID];  /* B-tree internal node 'K' values */
    H5F_file_t         *shared = NULL;      /* shared part of `file'        */
    H5FD_t             *lf = NULL;          /* file driver part of `shared' */
    uint8_t            *p;                  /* Temporary pointer into encoding buffers */
    unsigned            i;                  /* Index variable               */
    unsigned            chksum;             /* Checksum temporary variable  */
    size_t              driver_size;        /* Size of driver info block, in bytes */
    char                driver_name[9];     /* Name of driver, for driver info block */
    unsigned            super_vers;         /* Super block version          */
    unsigned            freespace_vers;     /* Freespace info version       */
    unsigned            obj_dir_vers;       /* Object header info version   */
    unsigned            share_head_vers;    /* Shared header info version   */
    uint8_t             buf[H5F_SUPERBLOCK_SIZE];     /* Local buffer                 */
    H5P_genplist_t     *c_plist;            /* File creation property list  */
    herr_t              ret_value = SUCCEED;

    /* Decoding */
    FUNC_ENTER_NOAPI(H5F_read_superblock, FAIL)

    /* Short cuts */
    shared = f->shared;
    lf = shared->lf;

    /* Get the shared file creation property list */
    if (NULL == (c_plist = H5I_object(shared->fcpl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")

    /* Read the superblock if it hasn't been read before. */
    if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id)))
        HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature")
    if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 ||
            H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, buf) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock")

    /* Signature, already checked */
    p = buf + H5F_SIGNATURE_LEN;

    /* Superblock version */
    super_vers = *p++;
    if (super_vers > HDF5_SUPERBLOCK_VERSION_MAX)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number")
    if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set superblock version")

    /* Freespace version */
    freespace_vers = *p++;
    if (HDF5_FREESPACE_VERSION != freespace_vers)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number")
    if (H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to free space version")

    /* Root group version number */
    obj_dir_vers = *p++;
    if (HDF5_OBJECTDIR_VERSION != obj_dir_vers)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad object directory version number")
    if (H5P_set(c_plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set object directory version")

    /* Skip over reserved byte */
    p++;

    /* Shared header version number */
    share_head_vers = *p++;
    if (HDF5_SHAREDHEADER_VERSION != share_head_vers)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad shared-header format version number")
    if (H5P_set(c_plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set shared-header format version")

    /* Size of file addresses */
    sizeof_addr = *p++;
    if (sizeof_addr != 2 && sizeof_addr != 4 &&
            sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address")
    if (H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number in an address")
    shared->sizeof_addr = sizeof_addr;  /* Keep a local copy also */

    /* Size of file sizes */
    sizeof_size = *p++;
    if (sizeof_size != 2 && sizeof_size != 4 &&
            sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size")
    if (H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number for object size")
    shared->sizeof_size = sizeof_size;  /* Keep a local copy also */

    /* Skip over reserved byte */
    p++;

    /* Various B-tree sizes */
    UINT16DECODE(p, sym_leaf_k);
    if (sym_leaf_k == 0)
        HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad symbol table leaf node 1/2 rank")
    if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes")
    shared->sym_leaf_k = sym_leaf_k;    /* Keep a local copy also */

    /* Need 'get' call to set other array values */
    if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes")
    UINT16DECODE(p, btree_k[H5B_SNODE_ID]);
    if (btree_k[H5B_SNODE_ID] == 0)
        HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad 1/2 rank for btree internal nodes")
    /*
     * Delay setting the value in the property list until we've checked
     * for the indexed storage B-tree internal 'K' value later.
     */

    /* File consistency flags. Not really used yet */
    UINT32DECODE(p, shared->consist_flags);
    assert(((size_t)(p - buf)) == fixed_size);

    /* Decode the variable-length part of the superblock... */
    variable_size = (super_vers>0 ? 4 : 0) +    /* Potential indexed storage B-tree internal 'K' value */
                    H5F_SIZEOF_ADDR(f) +        /*base addr*/
                    H5F_SIZEOF_ADDR(f) +        /*global free list*/
                    H5F_SIZEOF_ADDR(f) +        /*end-of-address*/
                    H5F_SIZEOF_ADDR(f) +        /*reserved address*/
                    H5G_SIZEOF_ENTRY(f);        /*root group ptr*/
    assert(fixed_size + variable_size <= sizeof(buf));
    if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 ||
            H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock")

    /*
     * If the superblock version # is greater than 0, read in the indexed
     * storage B-tree internal 'K' value
     */
    if (super_vers > 0) {
        UINT16DECODE(p, btree_k[H5B_ISTORE_ID]);
        p += 2;   /* reserved */
    }
    else
        btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF;

    /* Set the B-tree internal node values, etc */
    if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
    HDmemcpy(shared->btree_k, btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID);    /* Keep a local copy also */

    H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/);
    H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/);
    H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
    H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/);
    if (H5G_ent_decode(f, (const uint8_t **)&p, root_ent/*out*/) < 0)
        HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry")

    /*
     * Check if superblock address is different from base address and
     * adjust base address and "end of address" address if so.
     */
    if (!H5F_addr_eq(shared->super_addr,shared->base_addr)) {
        /* Check if the superblock moved earlier in the file */
        if (H5F_addr_lt(shared->super_addr, shared->base_addr))
            stored_eoa -= (shared->base_addr - shared->super_addr);
        else
            /* The superblock moved later in the file */
            stored_eoa += (shared->super_addr - shared->base_addr);

        shared->base_addr = shared->super_addr;
    } /* end if */

    /* Compute super block checksum */
    assert(sizeof(chksum) == sizeof(shared->super_chksum));
    for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < fixed_size + variable_size; ++i)
        q[i % sizeof(shared->super_chksum)] ^= buf[i];

    /* Set the super block checksum */
    shared->super_chksum = chksum;

    /* Decode the optional driver information block */
    if (H5F_addr_defined(shared->driver_addr)) {
        haddr_t drv_addr = shared->base_addr + shared->driver_addr;
        uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE];     /* Local buffer                 */

        if (H5FD_set_eoa(lf, drv_addr + 16) < 0 ||
                H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)16, dbuf) < 0)
            HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block")
        p = dbuf;

        /* Version number */
        if (HDF5_DRIVERINFO_VERSION != *p++)
            HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "bad driver information block version number")

        p += 3; /* reserved */

        /* Driver info size */
        UINT32DECODE(p, driver_size);

        /* Driver name and/or version */
        HDstrncpy(driver_name, (const char *)p, (size_t)8);
        driver_name[8] = '\0';
        p += 8; /* advance past name/version */

        /* Read driver information and decode */
        assert((driver_size + 16) <= sizeof(dbuf));
        if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 ||
                H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0)
            HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information")

        if (H5FD_sb_decode(lf, driver_name, p) < 0)
            HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information")

        /* Compute driver info block checksum */
        assert(sizeof(chksum) == sizeof(shared->drvr_chksum));
        for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i)
            q[i % sizeof(shared->drvr_chksum)] ^= dbuf[i];

        /* Set the driver info block checksum */
        shared->drvr_chksum = chksum;
    } /* end if */