hdf5/tools/lib/h5tools_ref.c

308 lines
7.7 KiB
C
Raw Normal View History

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <stdlib.h>
#include "h5tools_ref.h"
#include "H5private.h"
#include "h5tools.h"
#include "h5tools_utils.h"
/*
* Table to look up a path name for an object
* reference.
*
* This table stores mappings of reference -> path
* for all objects in the file that may be the target of
* an object reference.
*
* The 'path' is an absolute path by which the object
* can be accessed. When an object has > 1 such path,
* only one will be used in the table, with no particular
* method of selecting which one.
*/
extern hid_t thefile;
size_t prefix_len = 1024;
char *prefix;
extern char *progname;
extern int d_status;
ref_path_table_entry_t *ref_path_table = NULL; /* the table */
/*-------------------------------------------------------------------------
* Function: ref_path_table_lookup
*
* Purpose: Looks up a table entry given a path name.
* Used during construction of the table.
*
* Return: The table entre (pte) or NULL if not in the
* table.
*
* Programmer: REMcG
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
ref_path_table_entry_t *
ref_path_table_lookup(const char *thepath)
{
H5G_stat_t sb;
ref_path_table_entry_t *pte = ref_path_table;
if(H5Gget_objinfo(thefile, thepath, TRUE, &sb)<0)
/* fatal error ? */
return NULL;
while(pte!=NULL) {
if (sb.objno==pte->statbuf.objno)
return pte;
pte = pte->next;
}
return NULL;
}
/*-------------------------------------------------------------------------
* Function: ref_path_table_put
*
* Purpose: Enter the 'obj' with 'path' in the table if
* not already there.
* Create an object reference, pte, and store them
* in the table.
*
* Return: The object reference for the object.
*
* Programmer: REMcG
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
ref_path_table_entry_t *
ref_path_table_put(hid_t obj, const char *path)
{
ref_path_table_entry_t *pte;
/* look up 'obj'. If already in table, return */
pte = ref_path_table_lookup(path);
if (pte != NULL)
return pte;
/* if not found, then make new entry */
pte = (ref_path_table_entry_t *) malloc(sizeof(ref_path_table_entry_t));
if (pte == NULL)
/* fatal error? */
return NULL;
pte->obj = obj;
pte->apath = HDstrdup(path);
if(H5Gget_objinfo(thefile, path, TRUE, &pte->statbuf)<0) {
/* fatal error? */
free(pte);
return NULL;
}
pte->next = ref_path_table;
ref_path_table = pte;
return pte;
}
/*
* counter used to disambiguate multiple instances of same object.
*/
int xid = 1;
int get_next_xid() {
return xid++;
}
/*
* This counter is used to create fake object ID's
* The idea is to set it to the largest possible offest, which
* minimizes the chance of collision with a real object id.
*
*/
haddr_t fake_xid = HADDR_MAX;
haddr_t
get_fake_xid () {
return (fake_xid--);
}
/*
* for an object that does not have an object id (e.g., soft link),
* create a table entry with a fake object id as the key.
*/
ref_path_table_entry_t *
ref_path_table_gen_fake(const char *path)
{
ref_path_table_entry_t *pte;
/* look up 'obj'. If already in table, return */
pte = ref_path_table_lookup(path);
if (pte != NULL)
return pte;
/* if not found, then make new entry */
pte = (ref_path_table_entry_t *) malloc(sizeof(ref_path_table_entry_t));
if (pte == NULL)
/* fatal error? */
return NULL;
pte->obj = (hid_t)-1;
memset(&pte->statbuf,0,sizeof(H5G_stat_t));
pte->statbuf.objno = get_fake_xid();
pte->apath = HDstrdup(path);
pte->next = ref_path_table;
ref_path_table = pte;
return pte;
}
/*-------------------------------------------------------------------------
* Function: lookup_ref_path
*
* Purpose: Lookup the path to the object with refernce 'ref'.
*
* Return: Return a path to the object, or NULL if not found.
*
* Programmer: REMcG
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
char *
lookup_ref_path(hobj_ref_t ref)
{
ref_path_table_entry_t *pte = ref_path_table;
while(pte!=NULL) {
if (ref==pte->statbuf.objno)
return pte->apath;
pte = pte->next;
}
return NULL;
}
/*-------------------------------------------------------------------------
* Function: fill_ref_path_table
*
* Purpose: Called by interator to create references for
* all objects and enter them in the table.
*
* Return: Error status.
*
* Programmer: REMcG
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
fill_ref_path_table(hid_t group, const char *name, void UNUSED * op_data)
{
hid_t obj;
char *tmp;
size_t tmp_len;
H5G_stat_t statbuf;
ref_path_table_entry_t *pte;
char *thepath;
H5Gget_objinfo(group, name, FALSE, &statbuf);
tmp_len = strlen(prefix) + strlen(name) + 2;
tmp = (char *) malloc(tmp_len);
if (tmp == NULL)
return FAIL;
thepath = (char *) malloc(tmp_len);
if (thepath == NULL) {
free(tmp);
return FAIL;
}
strcpy(tmp, prefix);
strcpy(thepath, prefix);
strcat(thepath, "/");
strcat(thepath, name);
switch (statbuf.type) {
case H5G_DATASET:
if ((obj = H5Dopen(group, name)) >= 0) {
pte = ref_path_table_lookup(thepath);
if (pte == NULL)
ref_path_table_put(obj, thepath);
H5Dclose(obj);
} else {
error_msg(progname, "unable to get dataset \"%s\"\n", name);
d_status = EXIT_FAILURE;
}
break;
case H5G_GROUP:
if ((obj = H5Gopen(group, name)) >= 0) {
if (prefix_len <= tmp_len) {
prefix_len = tmp_len + 1;
prefix = realloc(prefix, prefix_len);
}
strcat(strcat(prefix, "/"), name);
pte = ref_path_table_lookup(thepath);
if (pte == NULL) {
ref_path_table_put(obj, thepath);
H5Giterate(obj, ".", NULL, fill_ref_path_table, NULL);
strcpy(prefix, tmp);
}
H5Gclose(obj);
} else {
error_msg(progname, "unable to dump group \"%s\"\n", name);
d_status = EXIT_FAILURE;
}
break;
case H5G_TYPE:
if ((obj = H5Topen(group, name)) >= 0) {
pte = ref_path_table_lookup(thepath);
if (pte == NULL)
ref_path_table_put(obj, thepath);
H5Tclose(obj);
} else {
error_msg(progname, "unable to get dataset \"%s\"\n", name);
d_status = EXIT_FAILURE;
}
break;
default:
break;
}
free(tmp);
free(thepath);
return 0;
}