2004-06-11 01:35:48 +08:00
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
|
* 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;
|
2005-04-21 14:55:42 +08:00
|
|
|
size_t prefix_len = 1024;
|
|
|
|
char *prefix;
|
2004-06-11 01:35:48 +08:00
|
|
|
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;
|
|
|
|
|
2004-12-29 22:26:20 +08:00
|
|
|
if(H5Gget_objinfo(thefile, thepath, TRUE, &sb)<0)
|
2004-06-11 01:35:48 +08:00
|
|
|
/* 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));
|
2004-12-29 22:26:20 +08:00
|
|
|
if (pte == NULL)
|
2004-06-11 01:35:48 +08:00
|
|
|
/* 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)
|
|
|
|
{
|
2004-12-29 22:26:20 +08:00
|
|
|
ref_path_table_entry_t *pte;
|
2004-06-11 01:35:48 +08:00
|
|
|
|
|
|
|
/* look up 'obj'. If already in table, return */
|
|
|
|
pte = ref_path_table_lookup(path);
|
2004-12-29 22:26:20 +08:00
|
|
|
if (pte != NULL)
|
2004-06-11 01:35:48 +08:00
|
|
|
return pte;
|
|
|
|
|
|
|
|
/* if not found, then make new entry */
|
|
|
|
|
|
|
|
pte = (ref_path_table_entry_t *) malloc(sizeof(ref_path_table_entry_t));
|
2004-12-29 22:26:20 +08:00
|
|
|
if (pte == NULL)
|
2004-06-11 01:35:48 +08:00
|
|
|
/* 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;
|
2005-04-21 14:55:42 +08:00
|
|
|
size_t tmp_len;
|
2004-06-11 01:35:48 +08:00
|
|
|
H5G_stat_t statbuf;
|
|
|
|
ref_path_table_entry_t *pte;
|
|
|
|
char *thepath;
|
|
|
|
|
|
|
|
H5Gget_objinfo(group, name, FALSE, &statbuf);
|
2005-04-21 14:55:42 +08:00
|
|
|
tmp_len = strlen(prefix) + strlen(name) + 2;
|
|
|
|
tmp = (char *) malloc(tmp_len);
|
2004-06-11 01:35:48 +08:00
|
|
|
|
|
|
|
if (tmp == NULL)
|
|
|
|
return FAIL;
|
|
|
|
|
2005-04-21 14:55:42 +08:00
|
|
|
thepath = (char *) malloc(tmp_len);
|
2004-06-11 01:35:48 +08:00
|
|
|
|
|
|
|
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);
|
2004-12-29 22:26:20 +08:00
|
|
|
if (pte == NULL)
|
2004-06-11 01:35:48 +08:00
|
|
|
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) {
|
2005-04-21 14:55:42 +08:00
|
|
|
if (prefix_len <= tmp_len) {
|
|
|
|
prefix_len = tmp_len + 1;
|
|
|
|
prefix = realloc(prefix, prefix_len);
|
|
|
|
}
|
|
|
|
|
2004-06-11 01:35:48 +08:00
|
|
|
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);
|
2004-12-29 22:26:20 +08:00
|
|
|
if (pte == NULL)
|
2004-06-11 01:35:48 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|