summaryrefslogtreecommitdiffstats
path: root/c++/src/H5PredType.h
Commit message (Expand)AuthorAgeFilesLines
* Change copyright headers to replace url referring to file to belrknox2017-05-161-6/+4
* Code improvementBinh-Minh Ribler2017-05-081-2/+2
* Format changes only.Binh-Minh Ribler2017-04-231-5/+5
* Miscellaneous clean-up: format and commentsBinh-Minh Ribler2017-04-131-3/+5
* Description:Binh-Minh Ribler2017-04-111-164/+164
* Purpose: Fix HDFFV-9532Binh-Minh Ribler2016-10-231-4/+0
* [svn-r27983] Description:Binh-Minh Ribler2015-10-071-162/+341
* [svn-r25062] Description:Binh-Minh Ribler2014-04-181-12/+12
* [svn-r25029] Purpose: Fixed HDFFV-3384Binh-Minh Ribler2014-04-121-12/+12
* [svn-r24290] Description:Binh-Minh Ribler2013-10-141-14/+19
* [svn-r24216] Purpose: Merged changes from trunkBinh-Minh Ribler2013-09-291-4/+6
* [svn-r22209] Purpose: Fixed bugs HDFFV-2761 & HDFFV-7852Binh-Minh Ribler2012-03-301-3/+12
* [svn-r15998] Description:Binh-Minh Ribler2008-10-301-1/+1
* [svn-r13253] Updated all C and C++ style source code files with the THG copyr...Albert Cheng2007-02-071-2/+3
* [svn-r13200] Purpose: Adding wrappers and fixing a bugBinh-Minh Ribler2007-01-261-0/+2
* [svn-r12404] Purpose: Fix typos/formatsBinh-Minh Ribler2006-06-051-14/+37
* [svn-r12216] Purpose:Quincey Koziol2006-04-101-0/+16
* [svn-r12200] Purpose: MaintenanceBinh-Minh Ribler2006-04-051-2/+2
* [svn-r12180] Purpose: MaintenanceBinh-Minh Ribler2006-03-301-2/+2
* [svn-r11755] Purpose: Code improvementBinh-Minh Ribler2005-12-031-61/+9
* [svn-r11555] Purpose: Code cleanupBinh-Minh Ribler2005-10-121-3/+3
* [svn-r11487] Purpose:Quincey Koziol2005-10-011-12/+12
* [svn-r11245] Purpose:Quincey Koziol2005-08-131-5/+5
* [svn-r11210] Purpose: Code improvementBinh-Minh Ribler2005-08-081-0/+4
* [svn-r9888] Purpose: Fixed bugBinh-Minh Ribler2005-01-301-3/+3
* [svn-r9129] Purpose: Updating documentationBinh-Minh Ribler2004-08-201-9/+16
* [svn-r6236] Purpose: CopyrightBinh-Minh Ribler2003-01-071-0/+14
* [svn-r5932] MuQun Yang2002-09-201-1/+1
* [svn-r4977] Binh-Minh Ribler2002-02-161-1/+1
* [svn-r4707] Binh-Minh Ribler2001-12-121-1/+1
* [svn-r4580] Binh-Minh Ribler2001-10-311-2/+5
* [svn-r3707] Purpose: Bug fixes and code clean upBinh-Minh Ribler2001-03-251-1/+51
* [svn-r3540] Purpose:Binh-Minh Ribler2001-03-021-1/+1
* [svn-r3534] Purpose:Bill Wendling2001-03-021-0/+1
* [svn-r2897] Purpose:Binh-Minh Ribler2000-11-141-0/+181
href='#n465'>465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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. *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*-------------------------------------------------------------------------
 *
 * Created:             H5Olink.c
 *                      Aug 29 2005
 *                      Quincey Koziol <koziol@ncsa.uiuc.edu>
 *
 * Purpose:             Link messages.
 *
 *-------------------------------------------------------------------------
 */

#define H5G_PACKAGE	/*suppress error about including H5Gpkg	  */
#define H5O_PACKAGE	/*suppress error about including H5Opkg	  */

#include "H5private.h"		/* Generic Functions			*/
#include "H5Eprivate.h"		/* Error handling		  	*/
#include "H5FLprivate.h"	/* Free lists                           */
#include "H5Gpkg.h"		/* Groups		  		*/
#include "H5Iprivate.h"         /* IDs                                  */
#include "H5Lprivate.h"		/* Links                                */
#include "H5MMprivate.h"	/* Memory management			*/
#include "H5Opkg.h"             /* Object headers			*/


/* PRIVATE PROTOTYPES */
static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p);
static herr_t H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg);
static void *H5O_link_copy(const void *_mesg, void *_dest);
static size_t H5O_link_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_link_reset(void *_mesg);
static herr_t H5O_link_free(void *_mesg);
/* static herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); */
static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type,
    const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
static void *H5O_link_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
    void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info,
    void *udata);
static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
    void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
    FILE * stream, int indent, int fwidth);

/* This message derives from H5O message class */
const H5O_msg_class_t H5O_MSG_LINK[1] = {{
    H5O_LINK_ID,            	/*message id number             */
    "link",                 	/*message name for debugging    */
    sizeof(H5O_link_t),     	/*native message size           */
    H5O_link_decode,        	/*decode message                */
    H5O_link_encode,        	/*encode message                */
    H5O_link_copy,          	/*copy the native value         */
    H5O_link_size,          	/*size of symbol table entry    */
    H5O_link_reset,		/* reset method			*/
    H5O_link_free,	        /* free method			*/
    H5O_link_delete,	       	/* file delete method		*/
    NULL,			/* link method			*/
    NULL,		    	/*get share method		*/
    NULL, 			/*set share method		*/
    NULL,		    	/*can share method		*/
    NULL, 			/*is shared method		*/
    H5O_link_pre_copy_file,	/* pre copy native value to file */
    H5O_link_copy_file,		/* copy native value to file    */
    H5O_link_post_copy_file,	/* post copy native value to file    */
    NULL,			/* get creation index		*/
    NULL,			/* set creation index		*/
    H5O_link_debug          	/*debug the message             */
}};

/* Current version of link information */
#define H5O_LINK_VERSION 	1

/* Flags for link flag encoding */
#define H5O_LINK_FLAG_HAS_CORDER        0x01

/* Declare a free list to manage the H5O_link_t struct */
H5FL_DEFINE_STATIC(H5O_link_t);


/*-------------------------------------------------------------------------
 * Function:    H5O_link_decode
 *
 * Purpose:     Decode a message and return a pointer to
 *              a newly allocated one.
 *
 * Return:      Success:        Ptr to new message in native order.
 *
 *              Failure:        NULL
 *
 * Programmer:  Quincey Koziol
 *              koziol@ncsa.uiuc.edu
 *              Aug 29 2005
 *
 *-------------------------------------------------------------------------
 */
static void *
H5O_link_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p)
{
    H5O_link_t          *lnk = NULL;    /* Pointer to link message */
    size_t              len;            /* Length of a string in the message */
    unsigned char       link_flags;     /* Flags for encoding link info */
    void                *ret_value;     /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_link_decode)

    /* check args */
    HDassert(f);
    HDassert(p);

    /* decode */
    if(*p++ != H5O_LINK_VERSION)
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")

    /* Allocate space for message */
    if(NULL == (lnk = H5FL_CALLOC(H5O_link_t)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Get the encoding flags for the link */
    link_flags = *p++;

    /* Get the type of the link */
    lnk->type = *p++;
    if(lnk->type < H5L_TYPE_HARD || lnk->type > H5L_TYPE_MAX)
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad link type")

    /* Get the link creation time from the file */
    if(link_flags & H5O_LINK_FLAG_HAS_CORDER) {
        INT64DECODE(p, lnk->corder)
        lnk->corder_valid = TRUE;
    } /* end if */
    else {
        lnk->corder = 0;
        lnk->corder_valid = FALSE;
    } /* end else */

    /* Get the link name's character set */
    lnk->cset = (H5T_cset_t)*p++;
    if(lnk->cset < H5T_CSET_ASCII || lnk->cset > H5T_CSET_UTF8)
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad cset type")

    /* Get the link's name */
    UINT32DECODE(p, len)
    if(len == 0)
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid name length")
    if(NULL == (lnk->name = H5MM_malloc(len + 1)))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
    HDmemcpy(lnk->name, p, len);
    lnk->name[len] = '\0';
    p += len;

    /* Get the appropriate information for each type of link */
    switch(lnk->type) {
        case H5L_TYPE_HARD:
            /* Get the address of the object the link points to */
            H5F_addr_decode(f, &p, &(lnk->u.hard.addr));
            break;

        case H5L_TYPE_SOFT:
            /* Get the link value */
            UINT16DECODE(p, len)
            if(len == 0)
                HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid link length")
            if(NULL == (lnk->u.soft.name = H5MM_malloc((size_t)len + 1)))
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
            HDmemcpy(lnk->u.soft.name, p, len);
            lnk->u.soft.name[len] = '\0';
            p += len;
            break;

        /* User-defined links */
        default:
            if(lnk->type < H5L_TYPE_UD_MIN || lnk->type > H5L_TYPE_MAX)
                HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unknown link type")

            /* A UD link.  Get the user-supplied data */
            UINT16DECODE(p, len)
            lnk->u.ud.size = len;
            if(len > 0)
            {
                if(NULL == (lnk->u.ud.udata = H5MM_malloc((size_t)len)))
                    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
                HDmemcpy(lnk->u.ud.udata, p, len);
                p += len;
            }
            else
                lnk->u.ud.udata = NULL;
    } /* end switch */

    /* Set return value */
    ret_value = lnk;

done:
    if(ret_value == NULL)
        if(lnk != NULL) {
            if(lnk->name != NULL)
                H5MM_xfree(lnk->name);
            if(lnk->type == H5L_TYPE_SOFT && lnk->u.soft.name != NULL)
                H5MM_xfree(lnk->u.soft.name);
            if(lnk->type >= H5L_TYPE_UD_MIN && lnk->u.ud.size > 0 && lnk->u.ud.udata != NULL)
                H5MM_xfree(lnk->u.ud.udata);
            H5FL_FREE(H5O_link_t, lnk);
        } /* end if */

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_decode() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_encode
 *
 * Purpose:     Encodes a link message.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              koziol@ncsa.uiuc.edu
 *              Aug 29 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg)
{
    const H5O_link_t       *lnk = (const H5O_link_t *) _mesg;
    size_t                  len;            /* Length of a string in the message */
    unsigned char           link_flags;     /* Flags for encoding link info */

    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_encode)

    /* check args */
    HDassert(f);
    HDassert(p);
    HDassert(lnk);

    /* encode */
    *p++ = H5O_LINK_VERSION;

    /* The encoding flags for the link */
    link_flags = lnk->corder_valid ? H5O_LINK_FLAG_HAS_CORDER : 0;
    *p++ = link_flags;

    /* Store the type of the link */
    *p++ = lnk->type;

    /* Store the link creation order in the file, if its valid */
    if(lnk->corder_valid)
        INT64ENCODE(p, lnk->corder)

    /* Store the link name's character set */
    *p++ = (uint8_t)lnk->cset;

    /* Store the link's name */
    len = HDstrlen(lnk->name);
    HDassert(len > 0);
    UINT32ENCODE(p, (uint32_t)len)
    HDmemcpy(p, lnk->name, len);
    p += len;

    /* Store the appropriate information for each type of link */
    switch(lnk->type) {
        case H5L_TYPE_HARD:
            /* Store the address of the object the link points to */
            H5F_addr_encode(f, &p, lnk->u.hard.addr);
            break;

        case H5L_TYPE_SOFT:
            /* Store the link value */
            len = (uint16_t)HDstrlen(lnk->u.soft.name);
            HDassert(len > 0);
            UINT16ENCODE(p, len)
            HDmemcpy(p, lnk->u.soft.name, len);
            p += len;
            break;

        /* User-defined links */
        default:
            HDassert(lnk->type >= H5L_TYPE_UD_MIN && lnk->type <= H5L_TYPE_MAX);

            /* Store the user-supplied data, however long it is */
            len = (uint16_t)lnk->u.ud.size;
            UINT16ENCODE(p, len)
            if(len > 0)
            {
                HDmemcpy(p, lnk->u.ud.udata, len);
                p+=len;
            }
            break;
    } /* end switch */

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_link_encode() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_copy
 *
 * Purpose:     Copies a message from _MESG to _DEST, allocating _DEST if
 *              necessary.
 *
 * Return:      Success:        Ptr to _DEST
 *
 *              Failure:        NULL
 *
 * Programmer:  Quincey Koziol
 *              koziol@ncsa.uiuc.edu
 *              Aug 29 2005
 *
 *-------------------------------------------------------------------------
 */
static void *
H5O_link_copy(const void *_mesg, void *_dest)
{
    const H5O_link_t    *lnk = (const H5O_link_t *) _mesg;
    H5O_link_t          *dest = (H5O_link_t *) _dest;
    void                *ret_value;     /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_link_copy)

    /* Check args */
    HDassert(lnk);
    if(!dest && NULL == (dest = H5FL_MALLOC(H5O_link_t)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Copy static information */
    *dest = *lnk;

    /* Duplicate the link's name */
    HDassert(lnk->name);
    if(NULL == (dest->name = H5MM_xstrdup(lnk->name)))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't duplicate link name")

    /* Copy other information needed for different link types */
    if(lnk->type == H5L_TYPE_SOFT) {
        if(NULL == (dest->u.soft.name = H5MM_xstrdup(lnk->u.soft.name)))
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't duplicate soft link value")
    } /* end if */
    else if(lnk->type >= H5L_TYPE_UD_MIN) {
        if(lnk->u.ud.size > 0) {
            if(NULL == (dest->u.ud.udata = H5MM_malloc(lnk->u.ud.size)))
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
            HDmemcpy(dest->u.ud.udata, lnk->u.ud.udata, lnk->u.ud.size);
        } /* end if */
    } /* end if */

    /* Set return value */
    ret_value = dest;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_copy() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_size
 *
 * Purpose:     Returns the size of the raw message in bytes not counting
 *              the message type or size fields, but only the data fields.
 *              This function doesn't take into account alignment.
 *
 * Return:      Success:        Message data size in bytes without alignment.
 *
 *              Failure:        zero
 *
 * Programmer:  Quincey Koziol
 *              koziol@ncsa.uiuc.edu
 *              Aug 29 2005
 *
 *-------------------------------------------------------------------------
 */
static size_t
H5O_link_size(const H5F_t *f, const void *_mesg)
{
    const H5O_link_t *lnk = (const H5O_link_t *)_mesg;
    size_t ret_value;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_size)

    /* Set return value */
    ret_value = 1 +                     /* Version */
                1 +                     /* Link encoding flags */
                1 +                     /* Link type */
                (lnk->corder_valid ? 8 : 0) + /* Creation order */
                1 +                     /* Character set */
                4 +                     /* Name length */
                HDstrlen(lnk->name);    /* Name */

    /* Add the appropriate length for each type of link */
    switch(lnk->type) {
        case H5L_TYPE_HARD:
            ret_value += H5F_SIZEOF_ADDR(f);
            break;

        case H5L_TYPE_SOFT:
            ret_value += 2 +                            /* Link value length */
                        HDstrlen(lnk->u.soft.name);     /* Link value */
            break;

        default: /* Default is user-defined link type */
            HDassert(lnk->type >= H5L_TYPE_UD_MIN);
            ret_value += 2 +                            /* User-defined data size */
                         lnk->u.ud.size;                /* User-defined data */
            break;
    } /* end switch */

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_size() */


/*-------------------------------------------------------------------------
 * Function:	H5O_link_reset
 *
 * Purpose:	Frees resources within a message, but doesn't free
 *		the message itself.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Quincey Koziol
 *		Monday, August 29, 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_reset(void *_mesg)
{
    H5O_link_t *lnk = (H5O_link_t *)_mesg;

    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_reset)

    if(lnk) {
        /* Free information for link (but don't free link pointer) */
        if(lnk->type == H5L_TYPE_SOFT)
            lnk->u.soft.name = H5MM_xfree(lnk->u.soft.name);
        else if (lnk->type >= H5L_TYPE_UD_MIN) {
            if(lnk->u.ud.size > 0)
                lnk->u.ud.udata = H5MM_xfree(lnk->u.ud.udata);
        } /* end if */
        lnk->name = H5MM_xfree(lnk->name);
    } /* end if */

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_link_reset() */


/*-------------------------------------------------------------------------
 * Function:	H5O_link_free
 *
 * Purpose:	Free's the message contents and the message itself
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Quincey Koziol
 *              Monday, August 29, 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_free(void *_mesg)
{
    H5O_link_t *lnk = (H5O_link_t *)_mesg;

    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_free)

    HDassert(lnk);

    /* Free information for link */
    H5O_link_reset(lnk);
    H5FL_FREE(H5O_link_t, lnk);

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_link_free() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_delete
 *
 * Purpose:     Free file space referenced by message
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              Monday, August 29, 2005
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link)
{
    const H5O_link_t *lnk = (const H5O_link_t *)_mesg;
    herr_t ret_value = SUCCEED;   /* Return value */

    FUNC_ENTER_NOAPI(H5O_link_delete, FAIL)

    /* check args */
    HDassert(f);
    HDassert(lnk);

    /* Check for adjusting the link count when the link is removed */
    if(adj_link) {
        /* Adjust the reference count of the object when a hard link is removed */
        if(lnk->type == H5L_TYPE_HARD) {
            H5O_loc_t oloc;

            /* Construct object location for object, in order to decrement it's ref count */
            H5O_loc_reset(&oloc);
            oloc.file = f;
            HDassert(H5F_addr_defined(lnk->u.hard.addr));
            oloc.addr = lnk->u.hard.addr;

            /* Decrement the ref count for the object */
            if(H5O_link(&oloc, -1, dxpl_id) < 0)
                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to decrement object link count")
        } /* end if */
        /* Perform the "delete" callback when a user-defined link is removed */
        else if(lnk->type >= H5L_TYPE_UD_MIN) {
            const H5L_class_t   *link_class;         /* User-defined link class */

            /* Get the link class for this type of link. */
            if(NULL == (link_class = H5L_find_class(lnk->type)))
                HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "link class not registered")

            /* Check for delete callback */
            if(link_class->del_func) {
                hid_t file_id;           /* ID for the file the link is located in (passed to user callback) */

                /* Get a file ID for the file the link is in */
                if((file_id = H5F_get_id(f)) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get file ID")

                /* Call user-defined link's 'delete' callback */
                if((link_class->del_func)(lnk->name, file_id, lnk->u.ud.udata, lnk->u.ud.size) < 0) {
                    H5I_dec_ref(file_id);
                    HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "link deletion callback returned failure")
                } /* end if */

                /* Release the file ID */
                if(H5I_dec_ref(file_id) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "can't close file")
            } /* end if */
        } /* end if */
    } /* end if */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_delete() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_pre_copy_file
 *
 * Purpose:     Perform any necessary actions before copying message between
 *              files for link messages.
 *
 * Return:      Success:        Non-negative
 *
 *              Failure:        Negative
 *
 * Programmer:  Quincey Koziol
 *              Monday, June 26, 2006
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *type,
    const void UNUSED *native_src, hbool_t *deleted, const H5O_copy_t *cpy_info,
    void UNUSED *udata)
{
    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_pre_copy_file)

    /* check args */
    HDassert(deleted);
    HDassert(cpy_info);

    /* If we are performing a 'shallow hierarchy' copy, and this link won't
     *  be included in the final group, indicate that it should be deleted
     *  in the destination object header before performing any other actions
     *  on it.
     */
    if(cpy_info->max_depth >= 0 && cpy_info->curr_depth >= cpy_info->max_depth)
        *deleted = TRUE;

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_link_pre_copy_file() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_copy_file
 *
 * Purpose:     Copies a message from _MESG to _DEST in file
 *
 * Return:      Success:        Ptr to _DEST
 *
 *              Failure:        NULL
 *
 * Programmer:  Quincey Koziol
 *              November  7, 2005
 *
 *-------------------------------------------------------------------------
 */
static void *
H5O_link_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type,
    void *native_src, H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id,
    H5O_copy_t UNUSED *cpy_info, void UNUSED *udata)
{
    H5O_link_t  *link_src = (H5O_link_t *)native_src;
    H5O_link_t  *link_dst = NULL;
    void        *ret_value;          /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_link_copy_file)

    /* check args */
    HDassert(link_src);
    HDassert(cpy_info);
    HDassert(cpy_info->max_depth < 0 || cpy_info->curr_depth < cpy_info->max_depth);

    /* Sanity check source link type */
    if(link_src->type > H5L_TYPE_SOFT && link_src->type < H5L_TYPE_UD_MIN)
        HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "unrecognized built-in link type")

    /* Allocate "blank" link for destination */
    /* (values will be filled in during 'post copy' operation) */
    if(NULL == (link_dst = H5FL_CALLOC(H5O_link_t)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Set return value */
    ret_value = link_dst;

done:
    if(!ret_value)
        if(link_dst)
            H5O_link_free(link_dst);

    FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_link_copy_file() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_post_copy_file
 *
 * Purpose:     Finish copying a message from between files
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              November  7, 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
    H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
{
    const H5O_link_t    *link_src = (const H5O_link_t *)mesg_src;
    H5O_link_t          *link_dst = (H5O_link_t *)mesg_dst;
    herr_t              ret_value = SUCCEED;    /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_link_post_copy_file)

    /* check args */
    HDassert(link_src);
    HDassert(dst_oloc);
    HDassert(H5F_addr_defined(dst_oloc->addr));
    HDassert(dst_oloc->file);
    HDassert(link_dst);
    HDassert(cpy_info);
    HDassert(cpy_info->max_depth < 0 || cpy_info->curr_depth < cpy_info->max_depth);

    /* Copy the link (and the object it points to) */
    if(H5G_link_copy_file(dst_oloc->file, dxpl_id, link_src, src_oloc, link_dst,
            cpy_info) < 0)
        HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy link")

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_link_post_copy_file() */


/*-------------------------------------------------------------------------
 * Function:    H5O_link_debug
 *
 * Purpose:     Prints debugging info for a message.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              koziol@ncsa.uiuc.edu
 *              Aug 29 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_link_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream,
	       int indent, int fwidth)
{
    const H5O_link_t    *lnk = (const H5O_link_t *) _mesg;
    herr_t               ret_value = SUCCEED;          /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_link_debug)

    /* check args */
    HDassert(f);
    HDassert(lnk);
    HDassert(stream);
    HDassert(indent >= 0);
    HDassert(fwidth >= 0);

    HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
	      "Link Type:", (lnk->type == H5L_TYPE_HARD ? "Hard" :
                  (lnk->type == H5L_TYPE_SOFT ? "Soft" :
                  (lnk->type == H5L_TYPE_EXTERNAL ? "External" :
                  (lnk->type >= H5L_TYPE_UD_MIN ? "User-defined" : "Unknown")))));

    if(lnk->corder_valid)
        HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
                  "Creation Order:", lnk->corder);

    HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
	      "Link Name Character Set:", (lnk->cset == H5T_CSET_ASCII ?
                "ASCII" : (lnk->cset == H5T_CSET_UTF8 ? "UTF-8" : "Unknown")));
    HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
	      "Link Name:", lnk->name);

    /* Display link-specific information */
    switch(lnk->type) {
        case H5L_TYPE_HARD:
            HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
                      "Object address:", lnk->u.hard.addr);
            break;

        case H5L_TYPE_SOFT:
            HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
                      "Link Value:", lnk->u.soft.name);
            break;

        default:
            if(lnk->type >= H5L_TYPE_UD_MIN) {
                if(lnk->type == H5L_TYPE_EXTERNAL) {
                    const char * objname = (const char *)lnk->u.ud.udata + (HDstrlen(lnk->u.ud.udata) + 1);

                    HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
                              "External File Name:", lnk->u.ud.udata);
                    HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
                              "External Object Name:", objname);
                } /* end if */
                else {
                    HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
                              "User-Defined Link Size:", lnk->u.ud.size);
                } /* end else */
            } /* end if */
            else
                HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type")
            break;
    } /* end switch */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_debug() */