Exemplo n.º 1
0
/*-------------------------------------------------------------------------
 * Function:	H5G_namei
 *
 * Purpose:	Translates a name to a symbol table entry.
 *
 *		If the specified name can be fully resolved, then this
 *		function returns the symbol table entry for the named object
 *		through the OBJ_ENT argument. The symbol table entry for the
 *		group containing the named object is returned through the
 *		GRP_ENT argument if it is non-null.  However, if the name
 *		refers to the root object then the GRP_ENT will be
 *		initialized with an undefined object header address.  The
 *		REST argument, if present, will point to the null terminator
 *		of NAME.
 *
 *		If the specified name cannot be fully resolved, then OBJ_ENT
 *		is initialized with the undefined object header address. The
 *		REST argument will point into the NAME argument to the start
 *		of the component that could not be located.  The GRP_ENT will
 *		contain the entry for the symbol table that was being
 *		searched at the time of the failure and will have an
 *		undefined object header address if the search failed at the
 *		root object. For instance, if NAME is `/foo/bar/baz' and the
 *		root directory exists and contains an entry for `foo', and
 *		foo is a group that contains an entry for bar, but bar is not
 *		a group, then the results will be that REST points to `baz',
 *		OBJ_ENT has an undefined object header address, and GRP_ENT
 *		is the symbol table entry for `bar' in `/foo'.
 *
 *		Every file has a root group whose name is `/'.  Components of
 *		a name are separated from one another by one or more slashes
 *		(/).  Slashes at the end of a name are ignored.  If the name
 *		begins with a slash then the search begins at the root group
 *		of the file containing LOC_ENT. Otherwise it begins at
 *		LOC_ENT.  The component `.' is a no-op, but `..' is not
 *		understood by this function (unless it appears as an entry in
 *		the symbol table).
 *
 *		Symbolic links are followed automatically, but if TARGET
 *		includes the H5G_TARGET_SLINK bit and the last component of
 *		the name is a symbolic link then that link is not followed.
 *		The *NLINKS value is decremented each time a link is followed
 *		and link traversal fails if the value would become negative.
 *		If NLINKS is the null pointer then a default value is used.
 *
 *		Mounted files are handled by calling H5F_mountpoint() after
 *		each step of the translation.  If the input argument to that
 *		function is a mount point then the argument shall be replaced
 *		with information about the root group of the mounted file.
 *		But if TARGET includes the H5G_TARGET_MOUNT bit and the last
 *		component of the name is a mount point then H5F_mountpoint()
 *		is not called and information about the mount point itself is
 *		returned.
 *
 * Errors:
 *
 * Return:	Success:	Non-negative if name can be fully resolved.
 *				See above for values of REST, GRP_ENT, and
 *				OBJ_ENT.  NLINKS has been decremented for
 *				each symbolic link that was followed.
 *
 *		Failure:	Negative if the name could not be fully
 *				resolved. See above for values of REST,
 *				GRP_ENT, and OBJ_ENT.
 *
 * Programmer:	Robb Matzke
 *		[email protected]
 *		Aug 11 1997
 *
 * Modifications:
 *      Robb Matzke, 2002-03-28
 *      The component name buffer on the stack has been replaced by
 *      a dynamically allocated buffer on the heap in order to
 *      remove limitations on the length of a name component.
 *      There are two reasons that the buffer pointer is global:
 *        (1) We want to be able to reuse the buffer without
 *            allocating and freeing it each time this function is
 *            called.
 *        (2) We need to be able to free it from H5G_term_interface()
 *            when the library terminates.
 *
 *      Pedro Vicente, <*****@*****.**> 22 Aug 2002
 *      Modified to deep copies of symbol table entries
 *      Added `id to name' support.
 *
 *      Quincey Koziol, 2003-01-06
 *      Added "action" and "ent" parameters to allow different actions when
 *      working on the last component of a name.  (Specifically, this allows
 *      inserting an entry into a group, instead of trying to look it up)
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5G_namei(const H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
          H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/,
          unsigned target, int *nlinks/*out*/, H5G_namei_act_t action,
          H5G_entry_t *ent, hid_t dxpl_id)
{
    H5G_entry_t		  _grp_ent;     /*entry for current group	*/
    H5G_entry_t		  _obj_ent;     /*entry found			*/
    size_t		  nchars;	/*component name length		*/
    int			  _nlinks = H5G_NLINKS;
    const char		   *s = NULL;
    unsigned null_obj;          /* Flag to indicate this function was called with obj_ent set to NULL */
    unsigned null_grp;          /* Flag to indicate this function was called with grp_ent set to NULL */
    unsigned obj_copy = 0;      /* Flag to indicate that the object entry is copied */
    unsigned group_copy = 0;    /* Flag to indicate that the group entry is copied */
    unsigned last_comp = 0;     /* Flag to indicate that a component is the last component in the name */
    unsigned did_insert = 0;    /* Flag to indicate that H5G_stab_insert was called */
    herr_t      ret_value=SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5G_namei);

    /* Set up "out" parameters */
    if (rest)
        *rest = name;
    if (!grp_ent) {
        grp_ent = &_grp_ent;
        null_grp = 1;
    } /* end if */
    else
        null_grp = 0;
    if (!obj_ent) {
        obj_ent = &_obj_ent;
        null_obj = 1;
    } /* end if */
    else
        null_obj = 0;
    if (!nlinks)
        nlinks = &_nlinks;

    /* Check args */
    if (!name || !*name)
        HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no name given");
    if (!loc_ent)
        HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group");

    /*
     * Where does the searching start?  For absolute names it starts at the
     * root of the file; for relative names it starts at CWG.
     */
    /* Check if we need to get the root group's entry */
    if('/' == *name) {
        H5G_t *tmp_grp;         /* Temporary pointer to root group of file */

        /* Look up root group for starting location */
        tmp_grp = H5G_rootof(loc_ent->file);
        HDassert(tmp_grp);

        /* Set the location entry to the root group's entry*/
        loc_ent = &(tmp_grp->ent);
    } /* end if */

    /* Deep copy of the symbol table entry (duplicates strings) */
    if(H5G_ent_copy(obj_ent, loc_ent, H5_COPY_DEEP) < 0)
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
        obj_copy = 1;

    H5G_ent_reset(grp_ent);

    /* Check for needing a larger buffer for the individual path name components */
    if((HDstrlen(name) + 1) > H5G_comp_alloc_g) {
        char *new_comp;                 /* New component buffer */
        size_t new_alloc;               /* New component buffer size */

        new_alloc = MAX3(1024, (2 * H5G_comp_alloc_g), (HDstrlen(name) + 1));
        if(NULL == (new_comp = H5MM_realloc(H5G_comp_g, new_alloc)))
            HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "unable to allocate component buffer")
            H5G_comp_g = new_comp;
        H5G_comp_alloc_g = new_alloc;
    } /* end if */

    /* traverse the name */
    while ((name = H5G_component(name, &nchars)) && *name) {
        /* Update the "rest of name" pointer */
        if(rest)
            *rest = name;

        /*
         * Copy the component name into a null-terminated buffer so
         * we can pass it down to the other symbol table functions.
         */
        HDmemcpy(H5G_comp_g, name, nchars);
        H5G_comp_g[nchars] = '\0';

        /*
         * The special name `.' is a no-op.
         */
        if ('.' == H5G_comp_g[0] && !H5G_comp_g[1]) {
            name += nchars;
            continue;
        } /* end if */

        /*
         * Advance to the next component of the name.
         */
        /* If we've already copied a new entry into the group entry,
         * it needs to be freed before overwriting it with another entry
         */
        if(group_copy)
            H5G_name_free(grp_ent);

        /* Transfer "ownership" of the entry's information to the group entry */
        H5G_ent_copy(grp_ent, obj_ent, H5_COPY_SHALLOW);
        H5G_ent_reset(obj_ent);

        /* Set flag that we've copied a new entry into the group entry */
        group_copy = 1;

        /* Check if this is the last component of the name */
        if(!((s=H5G_component(name+nchars, NULL)) && *s))
            last_comp=1;

        switch(action) {
        case H5G_NAMEI_TRAVERSE:
            if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/, dxpl_id )<0) {
                /*
                 * Component was not found in the current symbol table, possibly
                 * because GRP_ENT isn't a symbol table.
                 */
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
            }
            break;

        case H5G_NAMEI_INSERT:
            if(!last_comp) {
                if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/, dxpl_id )<0) {
                    /*
                     * Component was not found in the current symbol table, possibly
                     * because GRP_ENT isn't a symbol table.
                     */
                    HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
                }
            } /* end if */
            else {
                did_insert = 1;
                if(H5G_stab_insert(grp_ent, H5G_comp_g, ent, TRUE, dxpl_id) < 0)
                    HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert name")
                    HGOTO_DONE(SUCCEED);
            } /* end else */
            break;
        } /* end switch */

        /*
         * If we found a symbolic link then we should follow it.  But if this
         * is the last component of the name and the H5G_TARGET_SLINK bit of
         * TARGET is set then we don't follow it.
         */
        if(H5G_CACHED_SLINK==obj_ent->type &&
                (0==(target & H5G_TARGET_SLINK) || !last_comp)) {
            if ((*nlinks)-- <= 0)
                HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many links");
            if (H5G_traverse_slink (grp_ent, obj_ent, nlinks, dxpl_id)<0)
                HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link traversal failed");
        }

        /*
         * Resolve mount points to the mounted group.  Do not do this step if
         * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last
         * component of the name.
         */
        if (0==(target & H5G_TARGET_MOUNT) || !last_comp)
            H5F_mountpoint(obj_ent/*in,out*/);

        /* next component */
        name += nchars;
    } /* end while */

    /* Update the "rest of name" pointer */
    if (rest)
        *rest = name; /*final null */

    /* If this was an insert, make sure that the insert function was actually
     * called (this catches no-op names like "." and "/") */
    if(action == H5G_NAMEI_INSERT && !did_insert)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group already exists");

done:
    /* If we started with a NULL obj_ent, free the entry information */
    if(null_obj || (ret_value < 0 && obj_copy))
        H5G_name_free(obj_ent);
    /* If we started with a NULL grp_ent and we copied something into it, free the entry information */
    if(null_grp && group_copy)
        H5G_name_free(grp_ent);

    FUNC_LEAVE_NOAPI(ret_value);
}
Exemplo n.º 2
0
/*-------------------------------------------------------------------------
 * Function:	H5G_namei
 *
 * Purpose:	Translates a name to a symbol table entry.
 *
 *		If the specified name can be fully resolved, then this
 *		function returns the symbol table entry for the named object
 *		through the OBJ_ENT argument. The symbol table entry for the
 *		group containing the named object is returned through the
 *		GRP_ENT argument if it is non-null.  However, if the name
 *		refers to the root object then the GRP_ENT will be
 *		initialized with an undefined object header address.  The
 *		REST argument, if present, will point to the null terminator
 *		of NAME.
 *
 *		If the specified name cannot be fully resolved, then OBJ_ENT
 *		is initialized with the undefined object header address. The
 *		REST argument will point into the NAME argument to the start
 *		of the component that could not be located.  The GRP_ENT will
 *		contain the entry for the symbol table that was being
 *		searched at the time of the failure and will have an
 *		undefined object header address if the search failed at the
 *		root object. For instance, if NAME is `/foo/bar/baz' and the
 *		root directory exists and contains an entry for `foo', and
 *		foo is a group that contains an entry for bar, but bar is not
 *		a group, then the results will be that REST points to `baz',
 *		OBJ_ENT has an undefined object header address, and GRP_ENT
 *		is the symbol table entry for `bar' in `/foo'.
 *
 *		Every file has a root group whose name is `/'.  Components of
 *		a name are separated from one another by one or more slashes
 *		(/).  Slashes at the end of a name are ignored.  If the name
 *		begins with a slash then the search begins at the root group
 *		of the file containing LOC_ENT. Otherwise it begins at
 *		LOC_ENT.  The component `.' is a no-op, but `..' is not
 *		understood by this function (unless it appears as an entry in
 *		the symbol table).
 *
 *		Symbolic links are followed automatically, but if TARGET
 *		includes the H5G_TARGET_SLINK bit and the last component of
 *		the name is a symbolic link then that link is not followed.
 *		The *NLINKS value is decremented each time a link is followed
 *		and link traversal fails if the value would become negative.
 *		If NLINKS is the null pointer then a default value is used.
 *
 *		Mounted files are handled by calling H5F_mountpoint() after
 *		each step of the translation.  If the input argument to that
 *		function is a mount point then the argument shall be replaced
 *		with information about the root group of the mounted file.
 *		But if TARGET includes the H5G_TARGET_MOUNT bit and the last
 *		component of the name is a mount point then H5F_mountpoint()
 *		is not called and information about the mount point itself is
 *		returned.
 *
 * Errors:
 *
 * Return:	Success:	Non-negative if name can be fully resolved.
 *				See above for values of REST, GRP_ENT, and
 *				OBJ_ENT.  NLINKS has been decremented for
 *				each symbolic link that was followed.
 *
 *		Failure:	Negative if the name could not be fully
 *				resolved. See above for values of REST,
 *				GRP_ENT, and OBJ_ENT.
 *
 * Programmer:	Robb Matzke
 *		[email protected]
 *		Aug 11 1997
 *
 * Modifications:
 *      Robb Matzke, 2002-03-28
 *      The component name buffer on the stack has been replaced by
 *      a dynamically allocated buffer on the heap in order to
 *      remove limitations on the length of a name component.
 *      There are two reasons that the buffer pointer is global:
 *        (1) We want to be able to reuse the buffer without
 *            allocating and freeing it each time this function is
 *            called.
 *        (2) We need to be able to free it from H5G_term_interface()
 *            when the library terminates.
 *
 *      Pedro Vicente, <*****@*****.**> 22 Aug 2002
 *      Modified to deep copies of symbol table entries
 *      Added `id to name' support.
 *
 *      Quincey Koziol, 2003-01-06
 *      Added "action" and "ent" parameters to allow different actions when
 *      working on the last component of a name.  (Specifically, this allows
 *      inserting an entry into a group, instead of trying to look it up)
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5G_namei(const H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
	  H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/,
	  unsigned target, int *nlinks/*out*/, H5G_namei_act_t action,
          H5G_entry_t *ent, hid_t dxpl_id)
{
    H5G_entry_t		  _grp_ent;     /*entry for current group	*/
    H5G_entry_t		  _obj_ent;     /*entry found			*/
    size_t		  nchars;	/*component name length		*/
    int			  _nlinks = H5G_NLINKS;
    const char		   *s = NULL;
    unsigned null_obj;          /* Flag to indicate this function was called with obj_ent set to NULL */
    unsigned null_grp;          /* Flag to indicate this function was called with grp_ent set to NULL */
    unsigned obj_copy = 0;      /* Flag to indicate that the object entry is copied */
    unsigned group_copy = 0;    /* Flag to indicate that the group entry is copied */
    unsigned last_comp = 0;     /* Flag to indicate that a component is the last component in the name */
    unsigned did_insert = 0;    /* Flag to indicate that H5G_stab_insert was called */
    herr_t      ret_value=SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5G_namei);

    /* Set up "out" parameters */
    if (rest)
        *rest = name;
    if (!grp_ent) {
        grp_ent = &_grp_ent;
        null_grp = 1;
    } /* end if */
    else
        null_grp = 0;
    if (!obj_ent) {
        obj_ent = &_obj_ent;
        null_obj = 1;
    } /* end if */
    else
        null_obj = 0;
    if (!nlinks)
        nlinks = &_nlinks;

    /* Check args */
    if (!name || !*name)
        HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no name given");
    if (!loc_ent)
        HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group");

    /*
     * Where does the searching start?  For absolute names it starts at the
     * root of the file; for relative names it starts at CWG.
     */
    /* Check if we need to get the root group's entry */
    if('/' == *name) {
        H5G_t *tmp_grp;         /* Temporary pointer to root group of file */

        /* Look up root group for starting location */
        tmp_grp = H5G_rootof(loc_ent->file);
        HDassert(tmp_grp);

        /* Set the location entry to the root group's entry*/
        loc_ent = &(tmp_grp->ent);
    } /* end if */

    /* Deep copy of the symbol table entry (duplicates strings) */
    if(H5G_ent_copy(obj_ent, loc_ent, H5_COPY_DEEP) < 0)
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
    obj_copy = 1;

    H5G_ent_reset(grp_ent);

    /* Check for needing a larger buffer for the individual path name components */
    if(HDstrlen(name) + 1 > H5G_comp_alloc_g) {
        H5G_comp_alloc_g = MAX3(1024, 2 * H5G_comp_alloc_g, HDstrlen(name) + 1);
        H5G_comp_g = H5MM_realloc(H5G_comp_g, H5G_comp_alloc_g);
        if(!H5G_comp_g) {
            H5G_comp_alloc_g = 0;
            HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "unable to allocate component buffer")
        } /* end if */