/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Programmer: Robb Matzke * Friday, September 19, 1997 */ #define H5G_PACKAGE /*suppress error about including H5Gpkg */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ /* Packages needed by this file... */ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Gpkg.h" /* Groups */ #include "H5HLprivate.h" /* Local Heaps */ /* Private prototypes */ #ifdef NOT_YET static herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type); #endif /* NOT_YET */ /* Declare extern the PQ free list for the wrapped strings */ H5FL_BLK_EXTERN(str_buf); /*------------------------------------------------------------------------- * Function: H5G_ent_cache * * Purpose: Returns a pointer to the cache associated with the symbol * table entry. You should modify the cache directly, then call * H5G_ent_modified() with the new cache type (even if the type is * still the same). * * Return: Success: Ptr to the cache in the symbol table entry. * * Failure: NULL * * Programmer: Robb Matzke * Friday, September 19, 1997 * * Modifications: * *------------------------------------------------------------------------- */ const H5G_cache_t * H5G_ent_cache(const H5G_entry_t *ent, H5G_type_t *cache_type) { const H5G_cache_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_ent_cache, NULL); if (!ent) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "no entry"); if (cache_type) *cache_type = ent->type; /* Set return value */ ret_value=(const H5G_cache_t *)&(ent->cache); done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- * Function: H5G_ent_modified * * Purpose: This function should be called after you make any * modifications to a symbol table entry cache. Supply the new * type for the cache. If CACHE_TYPE is the constant * H5G_NO_CHANGE then the cache type isn't changed--just the * dirty bit is set. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, September 19, 1997 * * Modifications: * *------------------------------------------------------------------------- */ #ifdef NOT_YET static herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type) { FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_modified) HDassert(ent); /* Update cache type, if requested */ if (H5G_NO_CHANGE != cache_type) ent->type = cache_type; ent->dirty = TRUE; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_ent_modified */ #endif /* NOT_YET */ /*------------------------------------------------------------------------- * Function: H5G_ent_decode_vec * * Purpose: Same as H5G_ent_decode() except it does it for an array of * symbol table entries. * * Errors: * SYM CANTDECODE Can't decode. * * Return: Success: Non-negative, with *pp pointing to the first byte * after the last symbol. * * Failure: Negative * * Programmer: Robb Matzke * matzke@llnl.gov * Jul 18 1997 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5G_ent_decode_vec(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent, unsigned n) { unsigned u; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_ent_decode_vec, FAIL); /* check arguments */ assert(f); assert(pp); assert(ent); /* decode entries */ for (u = 0; u < n; u++) if (H5G_ent_decode(f, pp, ent + u) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode") done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- * Function: H5G_ent_decode * * Purpose: Decodes a symbol table entry pointed to by `*pp'. * * Errors: * * Return: Success: Non-negative with *pp pointing to the first byte * following the symbol table entry. * * Failure: Negative * * Programmer: Robb Matzke * matzke@llnl.gov * Jul 18 1997 * * Modifications: * Robb Matzke, 17 Jul 1998 * Added a 4-byte padding field for alignment and future expansion. * *------------------------------------------------------------------------- */ herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent) { const uint8_t *p_ret = *pp; uint32_t tmp; FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_decode); /* check arguments */ assert(f); assert(pp); assert(ent); ent->file = f; /* decode header */ H5F_DECODE_LENGTH(f, *pp, ent->name_off); H5F_addr_decode(f, pp, &(ent->header)); UINT32DECODE(*pp, tmp); *pp += 4; /*reserved*/ ent->type=(H5G_type_t)tmp; /* decode scratch-pad */ switch (ent->type) { case H5G_NOTHING_CACHED: break; case H5G_CACHED_STAB: assert(2 * H5F_SIZEOF_ADDR(f) <= H5G_SIZEOF_SCRATCH); H5F_addr_decode(f, pp, &(ent->cache.stab.btree_addr)); H5F_addr_decode(f, pp, &(ent->cache.stab.heap_addr)); break; case H5G_CACHED_SLINK: UINT32DECODE (*pp, ent->cache.slink.lval_offset); break; default: HDabort(); } *pp = p_ret + H5G_SIZEOF_ENTRY(f); FUNC_LEAVE_NOAPI(SUCCEED); } /*------------------------------------------------------------------------- * Function: H5G_ent_encode_vec * * Purpose: Same as H5G_ent_encode() except it does it for an array of * symbol table entries. * * Errors: * SYM CANTENCODE Can't encode. * * Return: Success: Non-negative, with *pp pointing to the first byte * after the last symbol. * * Failure: Negative * * Programmer: Robb Matzke * matzke@llnl.gov * Jul 18 1997 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5G_ent_encode_vec(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent, unsigned n) { unsigned u; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_ent_encode_vec, FAIL); /* check arguments */ assert(f); assert(pp); assert(ent); /* encode entries */ for (u = 0; u < n; u++) if (H5G_ent_encode(f, pp, ent + u) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode"); done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- * Function: H5G_ent_encode * * Purpose: Encodes the specified symbol table entry into the buffer * pointed to by *pp. * * Errors: * * Return: Success: Non-negative, with *pp pointing to the first byte * after the symbol table entry. * * Failure: Negative * * Programmer: Robb Matzke * matzke@llnl.gov * Jul 18 1997 * * Modifications: * * Robb Matzke, 8 Aug 1997 * Writes zeros for the bytes that aren't used so the file doesn't * contain junk. * *------------------------------------------------------------------------- */ herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent) { uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f); FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_encode); /* check arguments */ assert(f); assert(pp); if (ent) { /* encode header */ H5F_ENCODE_LENGTH(f, *pp, ent->name_off); H5F_addr_encode(f, pp, ent->header); UINT32ENCODE(*pp, ent->type); UINT32ENCODE(*pp, 0); /*reserved*/ /* encode scratch-pad */ switch (ent->type) { case H5G_NOTHING_CACHED: break; case H5G_CACHED_STAB: assert(2 * H5F_SIZEOF_ADDR(f) <= H5G_SIZEOF_SCRATCH); H5F_addr_encode(f, pp, ent->cache.stab.btree_addr); H5F_addr_encode(f, pp, ent->cache.stab.heap_addr); break; case H5G_CACHED_SLINK: UINT32ENCODE (*pp, ent->cache.slink.lval_offset); break; default: HDabort(); } } else { H5F_ENCODE_LENGTH(f, *pp, 0); H5F_addr_encode(f, pp, HADDR_UNDEF); UINT32ENCODE(*pp, H5G_NOTHING_CACHED); UINT32ENCODE(*pp, 0); /*reserved*/ } /* fill with zero */ while (*pp < p_ret) *(*pp)++ = 0; *pp = p_ret; FUNC_LEAVE_NOAPI(SUCCEED); } /*------------------------------------------------------------------------- * Function: H5G_ent_copy * * Purpose: Do a deep copy of symbol table entries * * Return: Success: 0, Failure: -1 * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: August 2002 * * Comments: * * Modifications: * Quincey Koziol, Sept. 25, 2002: * - Changed source & destination parameters to match the rest * of the functions in the library. * - Added 'depth' parameter to determine how much of the group * entry structure we want to copy. The new depths are: * H5G_COPY_NULL - Copy all the fields from the * source to the destination, but set the destination's * user path and canonical path to NULL. * H5G_COPY_LIMITED - Copy all the fields from the * source to the destination, except for the user path * field, keeping it the same as its * previous value in the destination. * H5G_COPY_SHALLOW - Copy all the fields from the source * to the destination, including the user path and * canonical path. (Destination "takes ownership" of * user and canonical paths) * H5G_COPY_DEEP - Copy all the fields from the source to * the destination, deep copying the user and canonical * paths. * *------------------------------------------------------------------------- */ herr_t H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_ent_copy_depth_t depth) { H5RS_str_t *tmp_user_path_r=NULL; /* Temporary string pointer for entry's user path */ FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_copy); /* Check arguments */ assert(src); assert(dst); /* If the depth is "very shallow", keep the old entry's user path */ if(depth==H5G_COPY_LIMITED) { tmp_user_path_r=dst->user_path_r; if(dst->canon_path_r) H5RS_decr(dst->canon_path_r); } /* end if */ /* Copy the top level information */ HDmemcpy(dst,src,sizeof(H5G_entry_t)); /* Deep copy the names */ if(depth==H5G_COPY_DEEP) { dst->user_path_r=H5RS_dup(src->user_path_r); dst->canon_path_r=H5RS_dup(src->canon_path_r); } else if(depth==H5G_COPY_LIMITED) { dst->user_path_r=tmp_user_path_r; dst->canon_path_r=H5RS_dup(src->canon_path_r); } else if(depth==H5G_COPY_NULL) { dst->user_path_r=NULL; dst->canon_path_r=NULL; } else if(depth==H5G_COPY_SHALLOW) { #ifndef NDEBUG /* Discarding 'const' qualifier OK - QAK */ H5G_ent_reset((H5G_entry_t *)src); #endif /* NDEBUG */ } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED); } /*------------------------------------------------------------------------- * Function: H5G_ent_reset * * Purpose: Reset a symbol table entry to an empty state * * Return: Success: 0, Failure: -1 * * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu * * Date: August 2005 * * Comments: * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5G_ent_reset(H5G_entry_t *ent) { FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_reset); /* Check arguments */ HDassert(ent); /* Clear the symbol table entry to an empty state */ HDmemset(ent, 0, sizeof(H5G_entry_t)); ent->header = HADDR_UNDEF; FUNC_LEAVE_NOAPI(SUCCEED); } /* end H5G_ent_reset() */ /*------------------------------------------------------------------------- * Function: H5G_ent_set_name * * Purpose: Set the name of a symbol entry OBJ, located at LOC * * Return: Success: 0, Failure: -1 * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: August 22, 2002 * *------------------------------------------------------------------------- */ herr_t H5G_ent_set_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name) { size_t name_len; /* Length of name to append */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5G_ent_set_name, FAIL) assert(loc); assert(obj); assert(name); /* Reset the object's previous names, if they exist */ if(obj->user_path_r) { H5RS_decr(obj->user_path_r); obj->user_path_r=NULL; } /* end if */ if(obj->canon_path_r) { H5RS_decr(obj->canon_path_r); obj->canon_path_r=NULL; } /* end if */ obj->user_path_hidden=0; /* Get the length of the new name */ name_len = HDstrlen(name); /* Modify the object's user path, if a user path exists in the location */ if(loc->user_path_r) { const char *loc_user_path; /* Pointer to raw string for user path */ size_t user_path_len; /* Length of location's user path name */ char *new_user_path; /* Pointer to new user path */ /* Get the length of the strings involved */ user_path_len = H5RS_len(loc->user_path_r); /* Modify the object's user path */ /* Get the raw string for the user path */ loc_user_path=H5RS_get_str(loc->user_path_r); assert(loc_user_path); /* The location's user path already ends in a '/' separator */ if ('/'==loc_user_path[user_path_len-1]) { if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") HDstrcpy(new_user_path, loc_user_path); } /* end if */ /* The location's user path needs a separator */ else { if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+1+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") HDstrcpy(new_user_path, loc_user_path); HDstrcat(new_user_path, "/"); } /* end else */ /* Append the component's name */ HDstrcat(new_user_path, name); /* Give ownership of the user path to the entry */ obj->user_path_r=H5RS_own(new_user_path); assert(obj->user_path_r); } /* end if */ /* Modify the object's canonical path, if a canonical path exists in the location */ if(loc->canon_path_r) { const char *loc_canon_path; /* Pointer to raw string for canonical path */ size_t canon_path_len; /* Length of location's canonical path name */ char *new_canon_path; /* Pointer to new canonical path */ /* Get the length of the strings involved */ canon_path_len = H5RS_len(loc->canon_path_r); /* Modify the object's canonical path */ /* Get the raw string for the canonical path */ loc_canon_path=H5RS_get_str(loc->canon_path_r); assert(loc_canon_path); /* The location's canonical path already ends in a '/' separator */ if ('/'==loc_canon_path[canon_path_len-1]) { if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") HDstrcpy(new_canon_path, loc_canon_path); } /* end if */ /* The location's canonical path needs a separator */ else { if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+1+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") HDstrcpy(new_canon_path, loc_canon_path); HDstrcat(new_canon_path, "/"); } /* end else */ /* Append the component's name */ HDstrcat(new_canon_path, name); /* Give ownership of the canonical path to the entry */ obj->canon_path_r=H5RS_own(new_canon_path); assert(obj->canon_path_r); } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_ent_set_name() */ /*------------------------------------------------------------------------- * Function: H5G_ent_debug * * Purpose: Prints debugging information about a symbol table entry. * * Errors: * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * matzke@llnl.gov * Aug 29 1997 * * Modifications: * Robb Matzke, 1999-07-28 * The HEAP argument is passed by value. *------------------------------------------------------------------------- */ herr_t H5G_ent_debug(H5F_t UNUSED *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * stream, int indent, int fwidth, haddr_t heap) { const char *lval = NULL; int nested_indent, nested_fwidth; FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_debug); /* Calculate the indent & field width values for nested information */ nested_indent=indent+3; nested_fwidth=MAX(0,fwidth-3); HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Name offset into private heap:", (unsigned long) (ent->name_off)); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Object header address:", ent->header); HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Dirty:", ent->dirty ? "Yes" : "No"); HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Cache info type:"); switch (ent->type) { case H5G_NOTHING_CACHED: HDfprintf(stream, "Nothing Cached\n"); break; case H5G_CACHED_STAB: HDfprintf(stream, "Symbol Table\n"); HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Cached entry information:"); HDfprintf(stream, "%*s%-*s %a\n", nested_indent, "", nested_fwidth, "B-tree address:", ent->cache.stab.btree_addr); HDfprintf(stream, "%*s%-*s %a\n", nested_indent, "", nested_fwidth, "Heap address:", ent->cache.stab.heap_addr); break; case H5G_CACHED_SLINK: HDfprintf (stream, "Symbolic Link\n"); HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Cached information:"); HDfprintf (stream, "%*s%-*s %lu\n", nested_indent, "", nested_fwidth, "Link value offset:", (unsigned long)(ent->cache.slink.lval_offset)); if (heap>0 && H5F_addr_defined(heap)) { const H5HL_t *heap_ptr; heap_ptr = H5HL_protect(ent->file, dxpl_id, heap); lval = H5HL_offset_into(ent->file, heap_ptr, ent->cache.slink.lval_offset); HDfprintf (stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth, "Link value:", lval); H5HL_unprotect(ent->file, dxpl_id, heap_ptr, heap); } else HDfprintf(stream, "%*s%-*s\n", nested_indent, "", nested_fwidth, "Warning: Invalid heap address given, name not displayed!"); break; default: HDfprintf(stream, "*** Unknown symbol type %d\n", ent->type); break; } FUNC_LEAVE_NOAPI(SUCCEED); }