/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #include #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; }