1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 /*****************************************************************************
16 
17  file - vgp.c
18 
19  Part of the Vset interface.
20  VGROUPs are handled by routines in here.
21 
22 
23 LOCAL ROUTINES
24 ==============
25  VIget_vgroup_node -- allocate a new VGROUP record
26  VIrelease_vgroup_node -- Releases a vgroup node
27  VIget_vginstance_node -- allocate a new vginstance_t record
28  VIrelease_vginstance_node -- Releases a vginstance node
29  Get_vfile    -- get vgroup file record
30  New_vfile    -- create new vgroup file record
31  Load_vfile   -- loads vgtab table with info of all vgroups in file.
32  Remove_vfile -- removes the file ptr from the vfile[] table.
33 
34  VPgetinfo  --  Read in the "header" information about the Vgroup.
35  VIstart    --  V-level initialization routine
36  VPshutdown  --  Terminate various static buffers.
37 
38 EXPORTED ROUTINES
39 =================
40  Following 4 routines are solely for B-tree routines.
41  vcompare     -- Compares two TBBT-tree keys for equality.  Similar to memcmp.
42  vprint       -- Prints out the key and reference number of VDatas and Vgroups
43  vdestroynode -- destroy vgroup node in TBBT
44  vfdestroynode  -- destroy vgroup file record node in TBBT
45  vtfreekey    -- Frees B-Tree index (actually doesn't anything at all)
46 
47  Vinitialize  -- initialize Vxxx interface
48  Vfinish      -- end Vxxx access to file
49 
50  vginstance   -- Looks thru vgtab for vgid and return the addr of the vg
51                   instance where vgid is found.
52  vexistvg     -- Tests if a vgroup with id "vgid" is in the file's vgtab.
53  vpackvg      -- Extracts fields from a VGROUP struct "vg" and packs the
54                   fields into array buf in preparation for storage in the
55                   HDF file.
56  vunpackvg    -- Unpacks the fields from a buf (ie a DFTAG_VG data object
57                   just read in from the HDF file), into a VGROUP structure vg.
58 
59  Vattach      -- Attaches to an existing vgroup or creates a new vgroup.
60  Vdetach      -- Detaches access to vg.
61  Vinsert      -- Inserts a velt (vs or vg) into a vg
62  Vflocate     -- Checks to see if the given field exists in a vdata
63                   belonging to this vgroup.
64  Vinqtagref   -- Checks whether the given tag/ref pair already exists
65                   in the vgroup.
66  Vntagrefs    -- Returns the number (0 or +ve integer) of tag/ref pairs
67                   in a vgroup.
68  Vnrefs       --
69  Vgettagrefs  -- Returns n tag/ref pairs from the vgroup into the
70                   caller-supplied arrays(tagrarray and refarray).
71  Vgettagref   -- Returns a specified tag/ref pair from the vgroup.
72  VQuerytag    -- Return the tag of this Vgroup.
73  VQueryref    -- Return the ref of this Vgroup.
74  Vaddtagref   -- Inserts a tag/ref pair into the attached vgroup vg.
75  vinsertpair  -- Inserts a tag/ref pair into the attached vgroup vg.
76  Ventries     -- Returns the num of entries (+ve integer) in the vgroup vgid.
77  Vsetname     -- Gives a name to the VGROUP vg.
78  Vsetclass    -- Assigns a class name to the VGROUP vg.
79  Visvg        -- Tests if the given entry in the vgroup vg is a VGROUP.
80  Visvs        -- Checks if an id in a vgroup refers to a VDATA.
81  Vgetid       -- Given a vgroup's id, returns the next vgroup's id in the file.
82  Vgetnext     -- Given the id of an entry from a vgroup vg, looks in vg
83                   for the next entry after it, and returns its id.
84  Vgetnamelen  -- Retrieves the length of the vgroup's name.
85  Vgetclassnamelen  -- Retrieves the length of the vgroup's classname.
86  Vgetname     -- Returns the vgroup's name.
87  Vgetclass    -- Returns the vgroup's class name .
88  Vgetvgroups  -- Gets user-created vgroups in a file or in a vgroup
89  Vinquire     -- General inquiry routine for VGROUP.
90  Vopen        -- This routine opens the HDF file and initializes it for
91                   Vset operations.(i.e." Hopen(); Vinitialize(f)").
92  Vclose       -- This routine closes the HDF file, after it has freed
93                   all memory and updated the file.
94                   (i.e." Vfinish(f); Hclose(f);").
95  Vdelete      -- Remove a Vgroup from its file.  This function will both
96                   remove the Vgoup from the internal Vset data structures
97                   as well as from the file.
98  Vdeletetagref - delete tag/ref pair in Vgroup
99 
100  NOTE: Another pass needs to made through this file to update some of
101        the comments about certain sections of the code. -GV 9/8/97
102 
103 *************************************************************************/
104 
105 #define VSET_INTERFACE
106 #include "hdf.h"
107 
108 /* These are used to determine whether a vgroup had been created by the
109    library internally, that is, not created by user's application */
110 #define HDF_NUM_INTERNAL_VGS        6
111 const char *HDF_INTERNAL_VGS[] = {_HDF_VARIABLE, _HDF_DIMENSION,
112 		 _HDF_UDIMENSION, _HDF_CDF, GR_NAME, RI_NAME};
113 
114 /* Prototypes */
115 extern VOID vprint(VOIDP k1);
116 
117 PRIVATE intn Load_vfile
118             (HFILEID f);
119 
120 PRIVATE intn Remove_vfile
121             (HFILEID f);
122 
123 PRIVATE intn vunpackvg
124             (VGROUP * vg, uint8 buf[], intn len);
125 
126 PRIVATE intn VIstart(void);
127 
128 /*
129    * --------------------------------------------------------------------
130    * PRIVATE  data structure and routines.
131    *
132    * Info about all vgroups in the file are loaded into vgtab  at start;
133    * and the vg field set to NULL until that vgroup is attached,
134    * and reset back to NULL when that vgroup is detached.
135    * Info about all vdatas in the file are loaded into vstab  at start;
136    * and the vs field set to NULL until that vdata is attached,
137    * and reset back to NULL when that vdata is detached.
138    * --------------------------------------------------------------------
139  */
140 
141 TBBT_TREE *vtree = NULL;
142 
143 /* Whether we've installed the library termination function yet for this interface */
144 PRIVATE intn library_terminate = FALSE;
145 
146 /* Temporary buffer for I/O */
147 PRIVATE uint32 Vgbufsize = 0;
148 PRIVATE uint8  *Vgbuf = NULL;
149 
150 /* Pointers to the VGROUP & vginstance node free lists */
151 static VGROUP       *vgroup_free_list     = NULL;
152 static vginstance_t *vginstance_free_list = NULL;
153 
154 /*******************************************************************************
155  NAME
156     VIget_vgroup_node -- allocate a new VGROUP record
157 
158  DESCRIPTION
159     Return a pointer to a new VGROUP to use for a new VGID.
160 
161  RETURNS
162     returns VGROUP record pointer or NULL if failed.
163 
164 *******************************************************************************/
165 VGROUP *
VIget_vgroup_node(void)166 VIget_vgroup_node(void)
167 {
168     VGROUP   *ret_value = NULL;
169     CONSTR(FUNC, "VIget_vgroup_node");
170 
171     /* clear error stack */
172     HEclear();
173 
174     /* Grab from free list if possible */
175     if(vgroup_free_list != NULL)
176       {
177         ret_value = vgroup_free_list;
178         vgroup_free_list = vgroup_free_list->next;
179       } /* end if */
180     else
181       {
182         if((ret_value = (VGROUP *)HDmalloc(sizeof(VGROUP))) == NULL)
183             HGOTO_ERROR(DFE_NOSPACE, NULL);
184       } /* end else */
185 
186     /* Initialize to zeros */
187     HDmemset(ret_value,0,sizeof(VGROUP));
188 
189 done:
190   if(ret_value == NULL)
191     { /* Error condition cleanup */
192 
193     } /* end if */
194 
195   /* Normal function cleanup */
196 
197   return(ret_value);
198 }	/* VIget_vgroup_node */
199 
200 /******************************************************************************
201  NAME
202    VIrelease_vgroup_node -- Releases a vgroup node
203 
204  DESCRIPTION
205     Puts an VGROUP node into the free list
206 
207  RETURNS
208     No return value
209 
210 *******************************************************************************/
VIrelease_vgroup_node(VGROUP * vg)211 void VIrelease_vgroup_node(VGROUP *vg)
212 {
213 #ifdef LATER
214     CONSTR(FUNC, "VIrelease_vgroup_node");	/* for HERROR */
215 #endif /* LATER */
216 
217     /* Insert the atom at the beginning of the free list */
218     vg->next         = vgroup_free_list;
219     vgroup_free_list = vg;
220 
221 }   /* end VIrelease_vgroup_node() */
222 
223 /******************************************************************************
224  NAME
225     VIget_vginstance_node -- allocate a new vginstance_t record
226 
227  DESCRIPTION
228     Return an pointer to a new vginstance to use for a new VGID.
229 
230  RETURNS
231     returns vginstance_t pointer or NULL if failed.
232 *******************************************************************************/
233 vginstance_t *
VIget_vginstance_node(void)234 VIget_vginstance_node(void)
235 {
236     vginstance_t   *ret_value = NULL;
237     CONSTR(FUNC, "VIget_vginstance_node");
238 
239     /* clear error stack */
240     HEclear();
241 
242     /* Grab from free list if possible */
243     if(vginstance_free_list != NULL)
244       {
245         ret_value = vginstance_free_list;
246         vginstance_free_list = vginstance_free_list->next;
247       } /* end if */
248     else
249       {
250         if((ret_value = (vginstance_t *)HDmalloc(sizeof(vginstance_t))) == NULL)
251             HGOTO_ERROR(DFE_NOSPACE, NULL);
252       } /* end else */
253 
254     /* Initialize to zeros */
255     HDmemset(ret_value,0,sizeof(vginstance_t));
256 
257 done:
258   if(ret_value == NULL)
259     { /* Error condition cleanup */
260 
261     } /* end if */
262 
263   /* Normal function cleanup */
264 
265   return(ret_value);
266 }	/* VIget_vginstance_node */
267 
268 /******************************************************************************
269  NAME
270     VIrelease_vginstance_node -- Releases a vginstance node
271 
272  DESCRIPTION
273     Puts a vginstance node into the free list
274 
275  RETURNS
276     No return value
277 
278 *******************************************************************************/
279 void
VIrelease_vginstance_node(vginstance_t * vg)280 VIrelease_vginstance_node(vginstance_t *vg /* IN: vgroup instance to release */)
281 {
282 #ifdef LATER
283     CONSTR(FUNC, "VIrelease_vginstance_node");	/* for HERROR */
284 #endif /* LATER */
285 
286     /* Insert the vsinstance at the beginning of the free list */
287     vg->next = vginstance_free_list;
288     vginstance_free_list = vg;
289 
290 }   /* end VIrelease_vginstance_node() */
291 
292 /*******************************************************************************
293 NAME
294   Get_vfile  -- get vgroup file record
295 
296 DESCRIPTION
297    Looks in the TBBT vtree for the file ID of the file.
298 
299 RETURNS
300    Returns a pointer to the vfile_t for that file on success, otherwise NULL.
301 
302 *******************************************************************************/
303 vfile_t *
Get_vfile(HFILEID f)304 Get_vfile(HFILEID f /* IN: file handle */)
305 {
306     VOIDP *t = NULL;       /* vfile_t pointer from tree */
307     int32 key = (int32)f;  /* initialize key to file handle */
308 
309     /* find file record */
310     t = (VOIDP *) tbbtdfind(vtree, (VOIDP) &key, NULL);
311 
312     return((vfile_t *)(t==NULL ? NULL : *t));
313 } /* end Get_vfile() */
314 
315 
316 /*******************************************************************************
317 NAME
318    New_vfile  -- create new vgroup file record
319 
320 DESCRIPTION
321    Creates vfile_t structure and adds it to the tree
322 
323 RETURNS
324    Returns a pointer to the vfile_t for that file on success, otherwise NULL.
325 
326 *******************************************************************************/
327 PRIVATE vfile_t *
New_vfile(HFILEID f)328 New_vfile(HFILEID f /* IN: file handle */)
329 {
330     vfile_t *v = NULL;
331 
332     /* Allocate the vfile_t structure */
333     if (NULL == (v = (vfile_t *) HDcalloc(1,sizeof(vfile_t))))
334       return(NULL);
335 
336     /* Assign the file ID & insert into the tree */
337     v->f = f;
338 
339     /* insert the vg instance in B-tree */
340     tbbtdins(vtree, (VOIDP) v, NULL);
341 
342     /* return vfile_t struct */
343     return(v);
344 } /* end New_vfile() */
345 
346 /*******************************************************************************
347 NAME
348    Load_vfile -- loads vgtab table with info of all vgroups in file.
349 
350 DESCRIPTION
351    *** Only called by Vinitialize()  ***
352 
353    loads vgtab table with info of all vgroups in file f.
354    Will allocate a new vfile_t, then proceed to load vg instances.
355 
356 RETURNS
357    RETURNS FAIL if error or no more file slots available.
358    RETURNS SUCCEED if ok.
359 
360 *******************************************************************************/
361 PRIVATE intn
Load_vfile(HFILEID f)362 Load_vfile(HFILEID f /* IN: file handle */)
363 {
364     vfile_t      *vf = NULL;
365     vginstance_t *v = NULL;
366     vsinstance_t *w = NULL;
367     int32       aid;
368     int32       ret;
369     uint16      tag = DFTAG_NULL;
370     uint16      ref = DFTAG_NULL;
371     intn        ret_value = SUCCEED;
372     CONSTR(FUNC, "Load_vfile");
373 
374     /* clear error stack */
375     HEclear();
376 
377     /* Check if vfile buffer has been allocated */
378     if (vtree == NULL)
379       {
380           vtree = tbbtdmake(vcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
381           if (vtree == NULL)
382               HGOTO_ERROR(DFE_NOSPACE, FAIL);
383 
384           /* Initialize the atom groups for Vdatas and Vgroups */
385           if (HAinit_group(VSIDGROUP,VATOM_HASH_SIZE) == FAIL)
386               HGOTO_ERROR(DFE_INTERNAL, FAIL);
387 
388           if (HAinit_group(VGIDGROUP,VATOM_HASH_SIZE) == FAIL)
389               HGOTO_ERROR(DFE_INTERNAL, FAIL);
390       }
391 
392     /* Grab the existing vfile_t structure first, otherwise create a new one */
393     if ((vf = Get_vfile(f)) == NULL)
394       {
395         if ((vf = New_vfile(f)) == NULL)
396             HGOTO_ERROR(DFE_FNF, FAIL);
397       }
398 
399     /* the file is already loaded (opened twice) do nothing */
400     if (vf->access++)
401         HGOTO_DONE(SUCCEED);
402 
403     /* load all the vg's  tag/refs from file */
404     vf->vgtabn = 0; /* intialize to number of current entries to zero */
405     vf->vgtree = tbbtdmake(vcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
406     if (vf->vgtree == NULL)
407         HGOTO_ERROR(DFE_NOSPACE, FAIL);
408 
409     ret = aid = Hstartread(f, DFTAG_VG, DFREF_WILDCARD);
410     while (ret != FAIL)
411       {
412           /* get tag/ref for this vgroup */
413           HQuerytagref(aid, &tag, &ref);
414 
415           /* get a vgroup struct to fill */
416           if (NULL == (v = VIget_vginstance_node()))
417             {
418                 tbbtdfree(vf->vgtree, vdestroynode, NULL);
419                 HGOTO_ERROR(DFE_NOSPACE, FAIL);
420             }
421 
422           vf->vgtabn++; /* increment number of vgroups found in file */
423 
424           v->key = (int32) ref;   /* set the key for the node */
425           v->ref = (uintn) ref;
426 
427           /* get the header information */
428           v->vg = VPgetinfo(f,ref);
429           if (v->vg == NULL)
430               HGOTO_ERROR(DFE_INTERNAL, FAIL);
431 
432           /* insert the vg instance in B-tree */
433           tbbtdins(vf->vgtree, (VOIDP) v, NULL);
434 
435           /* get next vgroup */
436           ret = Hnextread(aid, DFTAG_VG, DFREF_WILDCARD, DF_CURRENT);
437       }
438 
439     if (aid != FAIL)
440         Hendaccess(aid);
441 
442     /* clear error stack - this is to remove the faux errors about DD not
443        found from when Hstartread is called on a new file */
444     HEclear();
445 
446     /* load all the vs's  tag/refs from file */
447     vf->vstabn = 0;
448     vf->vstree = tbbtdmake(vcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
449     if (vf->vstree == NULL)
450       {
451           tbbtdfree(vf->vgtree, vdestroynode, NULL);
452           HGOTO_ERROR(DFE_NOSPACE, FAIL);
453       }     /* end if */
454 
455     ret = aid = Hstartread(f, VSDESCTAG, DFREF_WILDCARD);
456     while (ret != FAIL)
457       {
458           /* get tag/ref for this vdata */
459           HQuerytagref(aid, &tag, &ref);
460 
461           /* attach new vs to file's vstab */
462           if (NULL == (w = VSIget_vsinstance_node()))
463             {
464                 tbbtdfree(vf->vgtree, vdestroynode, NULL);
465                 tbbtdfree(vf->vstree, vsdestroynode, NULL);
466                 HGOTO_ERROR(DFE_NOSPACE, FAIL);
467             }
468 
469           vf->vstabn++; /* increment number of vdatas found in file */
470 
471           w->key = (int32) ref;   /* set the key for the node */
472           w->ref = (uintn)ref;
473 
474           /* get the header information */
475           w->vs = VSPgetinfo(f,ref);
476           if (w->vs == NULL)
477               HGOTO_ERROR(DFE_INTERNAL, FAIL);
478 
479           w->nattach = 0;
480           w->nvertices = 0;
481 
482           /* insert the vg instance in B-tree */
483           tbbtdins(vf->vstree, (VOIDP) w, NULL);
484 
485           /* get next vdata */
486           ret = Hnextread(aid, VSDESCTAG, DFREF_WILDCARD, DF_CURRENT);
487       }
488 
489     if (aid != FAIL)
490         Hendaccess(aid);
491 
492     /* clear error stack - this is to remove the faux errors about DD not
493        found from when Hstartread is called on a new file */
494     HEclear();
495 
496     /* file may be incompatible with vset version 2.x. Need to check it */
497     if (((int32) 0 == vf->vgtabn) && ((int32) 0 == vf->vstabn))
498       {
499         if ((int32) 0 == vicheckcompat(f))
500           {     /* not compatible */
501 #if 0
502               nvfile--;     /* delete the structure for that file */
503 #endif
504               tbbtdfree(vf->vgtree, vdestroynode, NULL);
505               tbbtdfree(vf->vstree, vsdestroynode, NULL);
506               HGOTO_ERROR(DFE_BADOPEN, FAIL);
507           }
508       }
509 
510 done:
511   if(ret_value == FAIL)
512     { /* Error condition cleanup */
513 
514     } /* end if */
515 
516   /* Normal function cleanup */
517 
518   return ret_value;
519 }   /* Load_vfile */
520 
521 /******************************************************************************
522 NAME
523    Remove_vfile -- removes the file ptr from the vfile[] table.
524 
525 DESCRIPTION
526    removes the file ptr from the vfile[] table.
527    *** Only called by Vfinish() ***
528 
529 RETURNS
530 
531 *******************************************************************************/
532 PRIVATE intn
Remove_vfile(HFILEID f)533 Remove_vfile(HFILEID f /* IN: file handle */)
534 {
535     VOIDP      *t  = NULL;
536     vfile_t    *vf = NULL;
537     intn       ret_value = SUCCEED;
538     CONSTR(FUNC, "Remove_vfile");
539 
540     /* clear error stack */
541     HEclear();
542 
543     /* Check if vfile buffer has been allocated */
544     if (vtree == NULL)
545         HGOTO_ERROR(DFE_INTERNAL, FAIL);
546 
547     /* Figure out what file to work on */
548     if ((vf = Get_vfile(f)) == NULL)
549         HGOTO_ERROR(DFE_FNF, FAIL);
550 
551     /* If someone still has an active pointer to this file
552        we don't remove it. */
553     if (--vf->access)
554         HGOTO_DONE(SUCCEED);
555 
556     /* clear out the tbbt's */
557     tbbtdfree(vf->vgtree, vdestroynode, NULL);
558     tbbtdfree(vf->vstree, vsdestroynode, NULL);
559 
560     /* Find the node in the tree */
561     if (( t = (VOIDP *) tbbtdfind(vtree, (VOIDP) &f, NULL)) == NULL)
562         HGOTO_DONE(FAIL);
563 
564     /* Delete the node and free the vfile_t stucture */
565     vf = tbbtrem((TBBT_NODE **) vtree, (TBBT_NODE *) t, NULL);
566     HDfree(vf);
567 
568 done:
569   if(ret_value == FAIL)
570     { /* Error condition cleanup */
571 
572     } /* end if */
573 
574   /* Normal function cleanup */
575 
576   return ret_value;
577 }   /* Remove_vfile */
578 
579 /******************************************************************************
580 NAME
581    vcompare  -- compare two TBBT keys for equality
582 
583 DESCRIPTION
584    Compares two B-tree keys for equality.  Similar to memcmp.
585 
586    *** Only called by B-tree routines, should _not_ be called externally ***
587 
588 RETURNS
589 
590 *******************************************************************************/
591 intn
vcompare(VOIDP k1,VOIDP k2,intn cmparg)592 vcompare(VOIDP k1,   /* IN: first key to compare*/
593          VOIDP k2,   /* IN: second key to compare */
594          intn cmparg /* IN: not used */)
595 {
596   /* shut compiler up */
597   cmparg = cmparg;
598 
599   return (intn) ((*(int32 *)k1) - (*(int32 *)k2));    /* valid for integer keys */
600 }   /* vcompare */
601 
602 /******************************************************************************
603 NAME
604   vprint -- print key and reference number of vgroup/vdata node in TBBT
605 
606 DESCRIPTION
607    Prints out the key and reference number of VDatas and Vgroups
608 
609    *** Only called by B-tree routines, should _not_ be called externally ***
610 
611 RETURNS
612 
613 *******************************************************************************/
614 VOID
vprint(VOIDP k1)615 vprint(VOIDP k1 /* IN: key to print */)
616 {
617     printf("Ptr=%p, key=%d, ref=%d\n",
618            k1, (int) ((vginstance_t *) k1)->key, (int) ((vginstance_t *) k1)->ref);
619 }   /* vprint */
620 
621 /******************************************************************************
622 NAME
623    vdestroynode -- destroy vgroup node in TBBT
624 
625 DESCRIPTION
626    Frees B-Tree nodes
627 
628    *** Only called by B-tree routines, should _not_ be called externally ***
629 
630 RETURNS
631    Nothing
632 
633 *******************************************************************************/
634 VOID
vdestroynode(VOIDP n)635 vdestroynode(VOIDP n /* IN: node to free */)
636 {
637     VGROUP     *vg = NULL;
638 
639     if (n != NULL)
640       {
641           vg = ((vginstance_t *) n)->vg;
642           if (vg != NULL)
643             {
644                 HDfree((VOIDP) vg->tag);
645                 HDfree((VOIDP) vg->ref);
646 
647                 if (vg->vgname != NULL)
648                     HDfree((VOIDP) vg->vgname);
649 
650                 if (vg->vgclass != NULL)
651                     HDfree((VOIDP) vg->vgclass);
652 
653                 if (vg->alist != NULL)
654                     HDfree((VOIDP) vg->alist);
655 
656 		/* Free the old-style attr list and reset associated fields */
657                 if (vg->old_alist != NULL)
658 		{
659                     HDfree((VOIDP) vg->old_alist);
660 		    vg->old_alist = NULL;
661 		    vg->noldattrs = 0;
662 		}
663 
664                 VIrelease_vgroup_node(vg);
665             }
666 
667           VIrelease_vginstance_node((vginstance_t *)n);
668       } /* end if n */
669 }   /* vdestroynode */
670 
671 /*******************************************************************************
672 NAME
673    vfdestroynode  -- destroy vgroup file record node in TBBT
674 
675 DESCRIPTION
676    Frees B-Tree vfile_t nodes
677 
678    *** Only called by B-tree routines, should _not_ be called externally ***
679 
680 RETURNS
681    Nothing
682 
683 *******************************************************************************/
684 VOID
vfdestroynode(VOIDP n)685 vfdestroynode(VOIDP n /* IN: vfile_t record to free */)
686 {
687     vfile_t      *vf = NULL;
688 
689     if (n != NULL)
690       {
691           vf=(vfile_t *)n;
692 
693           /* clear out the tbbt's */
694           tbbtdfree(vf->vgtree, vdestroynode, NULL);
695           tbbtdfree(vf->vstree, vsdestroynode, NULL);
696 
697           HDfree(vf);
698       }
699 }   /* vfdestroynode */
700 
701 #ifdef NOTNEEDED
702 /* ---------------------------- vtfreekey ------------------------- */
703 /*
704    Frees B-Tree index (actually doesn't anything at all)
705 
706    *** Only called by B-tree routines, should _not_ be called externally ***
707  */
708 VOID
vtfreekey(VOIDP k)709 vtfreekey(VOIDP k)
710 {
711     k = k;  /* i.e. do nothing */
712 }   /* vtfreekey */
713 #endif
714 
715 /*******************************************************************************
716 NAME
717    Vinitialize  -- initialize Vxxx interface
718 
719 DESCRIPTION
720     Initialize Vxxx stuff/interface ?
721 
722 RETURNS
723     SUCCEED / FAIL
724 
725 *******************************************************************************/
726 intn
Vinitialize(HFILEID f)727 Vinitialize(HFILEID f /* IN: file handle */)
728 {
729     intn   ret_value = SUCCEED;
730     CONSTR(FUNC, "Vinitialize");
731 
732     /* clear error stack */
733     HEclear();
734 
735     /* Perform global, one-time initialization */
736     if (library_terminate == FALSE)
737       {
738         if(VIstart()==FAIL)
739             HGOTO_ERROR(DFE_CANTINIT, FAIL);
740       }
741 
742     /* load Vxx stuff from file? */
743     if (Load_vfile(f) == FAIL)
744         HGOTO_ERROR(DFE_INTERNAL, FAIL);
745 
746 done:
747   if(ret_value == FAIL)
748     { /* Error condition cleanup */
749 
750     } /* end if */
751 
752   /* Normal function cleanup */
753   return ret_value;
754 } /* Vinitialize() */
755 
756 
757 /*******************************************************************************
758 NAME
759    Vfinish  -- end Vxxx access to file
760 
761 DESCRIPTION
762    End Vxxx acess to file?
763 
764 RETURNS
765    SUCCEED / FAIL
766 
767 *******************************************************************************/
768 intn
Vfinish(HFILEID f)769 Vfinish(HFILEID f /* IN: file handle */)
770 {
771   intn    ret_value = SUCCEED;
772   CONSTR(FUNC, "Vfinish");
773 
774   /* clear error stack */
775   HEclear();
776 
777   /* remove Vxxx file record ? */
778   if (Remove_vfile(f) == FAIL)
779       HGOTO_ERROR(DFE_INTERNAL, FAIL);
780 
781 done:
782   if(ret_value == FAIL)
783     { /* Error condition cleanup */
784 
785     } /* end if */
786 
787   /* Normal function cleanup */
788   return ret_value;
789 } /* Vfinish() */
790 
791 /*******************************************************************************
792 NAME
793    vginst
794 
795 DESCRIPTION
796    Looks thru vgtab for vgid and return the addr of the vg instance
797    where vgid is found.
798 
799 RETURNS
800    RETURNS NULL if error or not found.
801    RETURNS vginstance_t pointer if ok.
802 
803 *******************************************************************************/
804 vginstance_t *
vginst(HFILEID f,uint16 vgid)805 vginst(HFILEID f,   /* IN: file handle */
806        uint16 vgid  /* IN: vgroup id */)
807 {
808     VOIDP        *t = NULL;
809     vfile_t      *vf = NULL;
810     vginstance_t *ret_value = NULL;
811     int32        key;
812     CONSTR(FUNC, "vginstance");
813 
814     /* clear error stack */
815     HEclear();
816 
817     /* get file Vxxx file record */
818     if (NULL == (vf = Get_vfile(f)))
819         HGOTO_ERROR(DFE_FNF, NULL);
820 
821     /* tbbtdfind returns a pointer to the vginstance_t pointer */
822     key = (int32)vgid;
823     t = (VOIDP *) tbbtdfind(vf->vgtree, (VOIDP) &key, NULL);
824     if (t != NULL)
825       {
826         ret_value = ((vginstance_t *) * t);  /* return the actual vginstance_t ptr */
827         goto done;
828       }
829 
830     /* we get here then we did find vgroup */
831     HGOTO_ERROR(DFE_NOMATCH, NULL);
832 
833 done:
834   if(ret_value == NULL)
835     { /* Error condition cleanup */
836 
837     } /* end if */
838 
839   /* Normal function cleanup */
840 
841   return ret_value;
842 }   /* vginst */
843 
844 /*******************************************************************************
845 NAME
846    vexistvg
847 
848 DESCRIPTION
849    Tests if a vgroup with id vgid is in the file's vgtab.
850 
851 RETURNS
852    returns FAIL if not found,
853    returns TRUE if found.
854 
855 *******************************************************************************/
856 int32
vexistvg(HFILEID f,uint16 vgid)857 vexistvg(HFILEID f,   /* IN: file handle */
858          uint16 vgid  /* IN: vgroup id */)
859 {
860     int32   ret_value;
861 #ifdef LATER
862     CONSTR(FUNC, "vexistvg");
863 #endif
864 
865     if (NULL == (vginstance_t *) vginst(f, vgid))
866         ret_value = (FAIL);
867     else
868         ret_value =  (TRUE);
869 
870   return ret_value;
871 }   /* vexistvg */
872 
873 /* ==================================================================== */
874 /*
875    * vpackvg() and vunpackvg() : Packing and unpacking routines.
876    * For use in retrieving and storing vgroups to/from the HDF file.
877    *
878    *    Fields of VGROUP  that gets stored in HDF as a DFTAG_VG data object:
879    *            int16           nvelt (no of entries )
880    *            char*           vgname
881    *            char*           vgclass
882    *            int16           tag[1..nvelt]
883    *            int16           ref[1..nvelt]
884    *    (fields for version 4)
885    *            uint32   flags
886    *    (if bit0 of flags is set, the vg has attributes )
887    *            int32    nattrs
888    *            vg_attr_t alist[1..nattrs]
889  */
890 /* ==================================================================== */
891 
892 /*******************************************************************************
893 NAME
894    vpackvg
895 
896 DESCRIPTION
897    Extracts fields from a VGROUP struct vg and packs the fields
898    into array buf in preparation for storage in the HDF file.
899 
900 RETRUNS
901    NO RETURN VALUES.
902 
903 *******************************************************************************/
904 intn
vpackvg(VGROUP * vg,uint8 buf[],int32 * size)905 vpackvg(VGROUP * vg, /* IN: */
906         uint8 buf[], /* IN/OUT: */
907         int32 *size  /* IN/OUT: */)
908 {
909 #ifdef LATER
910     CONSTR(FUNC, "vpackvg");
911 #endif
912     uintn  i;
913     size_t slen = 0;
914     uint16 temp_len = 0;
915     uint8 *bb = NULL;
916     int32 ret_value = SUCCEED;
917 
918     /* clear error stack */
919     HEclear();
920 
921     bb = &buf[0];
922 
923     /* save nvelt */
924     UINT16ENCODE(bb, vg->nvelt);
925 
926     /* save all tags */
927     for (i = 0; i < (uintn)vg->nvelt; i++)
928         UINT16ENCODE(bb, vg->tag[i]);
929 
930     /* save all refs */
931     for (i = 0; i < (uintn)vg->nvelt; i++)
932         UINT16ENCODE(bb, vg->ref[i]);
933 
934     /* save the vgnamelen and vgname - omit the null */
935     if (vg->vgname != NULL)
936         slen = HDstrlen(vg->vgname);
937     temp_len = slen > 0 ? slen : 0;
938     UINT16ENCODE(bb, temp_len);
939 
940     if (vg->vgname != NULL)
941         HDstrcpy((char *) bb, vg->vgname);
942     bb += temp_len;
943 
944     /* save the vgclasslen and vgclass- omit the null */
945     slen = 0;
946     if (vg->vgclass != NULL)
947         slen = HDstrlen(vg->vgclass);
948     temp_len = slen > 0 ? slen : 0;
949     UINT16ENCODE(bb, temp_len);
950 
951     if (vg->vgclass != NULL)
952         HDstrcpy((char *) bb, vg->vgclass);
953     bb += temp_len;
954 
955     /* save the expansion tag/ref pair */
956     UINT16ENCODE(bb, vg->extag);    /* the vg's expansion tag */
957     UINT16ENCODE(bb, vg->exref);    /* the vg's expansion ref */
958 
959     if (vg->flags)
960       {   /* save the flag and update version num */
961           if (vg->version < VSET_NEW_VERSION)
962               vg->version = VSET_NEW_VERSION;
963 
964           UINT32ENCODE(bb, vg->flags);
965 
966           if (vg->flags & VG_ATTR_SET)
967             {   /* save the attrs */
968                 INT32ENCODE(bb, vg->nattrs);
969 
970                 for (i=0; i<(uintn)vg->nattrs; i++)
971                   {
972                       UINT16ENCODE(bb, vg->alist[i].atag);
973                       UINT16ENCODE(bb, vg->alist[i].aref);
974                   }
975             }
976       }
977 
978     /*  save the vg's version field */
979     UINT16ENCODE(bb, vg->version);
980 
981     /* save the vg's more field */
982     UINT16ENCODE(bb, vg->more);
983 
984     /* returns the size of total fields saved */
985     *size = (int32) (bb - buf) + 1;
986     *bb = 0;       /* NOTE: the '+1' part shouldn't be there */
987     /* but since files have been created with */
988     /* it there (and the size calc. wrong) it */
989     /* has to be left alone -QAK */
990 
991 #ifdef LATER
992 done:
993     if (ret_value == FAIL)
994     { /* Error condition cleanup */
995 
996     } /* end if */
997 #endif /* LATER */
998 
999   /* Normal function cleanup */
1000   return ret_value;
1001 }   /* vpackvg */
1002 
1003 /*******************************************************************************
1004 NAME
1005    vunpackvg:
1006 
1007 DESCRIPTION
1008    Unpacks the fields from a buf (ie a DFTAG_VG data object just
1009    read in from the HDF file), into a VGROUP structure vg.
1010    Will first zero out vg, unpack fields, then inits as much of
1011    vg as it can.
1012 
1013 RETURNS
1014    NO RETURN VALUES
1015 
1016 *******************************************************************************/
1017 PRIVATE intn
vunpackvg(VGROUP * vg,uint8 buf[],intn len)1018 vunpackvg(VGROUP * vg, /* IN/OUT: */
1019           uint8 buf[], /* IN: */
1020           intn len     /* IN: */)
1021 {
1022     uint8 *bb = NULL;
1023     uintn u;
1024     uint16 uint16var;
1025     intn i;
1026     int32 ret_value = SUCCEED;
1027     CONSTR(FUNC, "vunpackvg");
1028 
1029     /* clear error stack */
1030     HEclear();
1031 
1032     /* '5' is a magic number, the exact amount of space for 2 uint16's */
1033     /* the magic number _should_ be '4', but the size of the Vgroup */
1034     /* information is incorrectly calculated (in vpackvg() above) when the */
1035     /* info is written to the file and it's too late to change it now :-( */
1036     bb = &buf[len - 5];
1037 
1038     UINT16DECODE(bb, uint16var);  /* retrieve the vg's version field */
1039     vg->version=(int16)uint16var;
1040 
1041     UINT16DECODE(bb, uint16var);     /* retrieve the vg's more field */
1042     vg->more=(int16)uint16var;
1043 
1044     bb = &buf[0];
1045 
1046     /* retrieve nvelt */
1047     if (vg->version <= 4)
1048       {     /* current Vset version number */
1049           UINT16DECODE(bb, vg->nvelt);
1050 
1051           vg->msize = ((uintn)vg->nvelt > (uintn)MAXNVELT ? vg->nvelt : MAXNVELT);
1052           vg->tag = (uint16 *) HDmalloc(vg->msize * sizeof(uint16));
1053           vg->ref = (uint16 *) HDmalloc(vg->msize * sizeof(uint16));
1054 
1055           if ((vg->tag == NULL) || (vg->ref == NULL))
1056               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1057 
1058           /* retrieve the tags */
1059           for (u = 0; u < (uintn)vg->nvelt; u++)
1060               UINT16DECODE(bb, vg->tag[u]);
1061 
1062           /* retrieve the refs */
1063           for (u = 0; u < (uintn)vg->nvelt; u++)
1064               UINT16DECODE(bb, vg->ref[u]);
1065 
1066           /* retrieve vgname (and its len)  */
1067           UINT16DECODE(bb, uint16var);
1068 	  if (uint16var == 0)
1069 	      vg->vgname = NULL;
1070 	  else
1071 	  {
1072 	      vg->vgname = (char *)HDmalloc(uint16var+1);
1073               HIstrncpy(vg->vgname, (char *) bb, (intn) uint16var + 1);
1074               bb += (size_t)uint16var;
1075 	  }
1076 
1077           /* retrieve vgclass (and its len)  */
1078           UINT16DECODE(bb, uint16var);
1079 	  if (uint16var == 0)
1080 	      vg->vgclass = NULL;
1081 	  else
1082 	  {
1083 	      vg->vgclass = (char *)HDmalloc(uint16var+1);
1084               HIstrncpy(vg->vgclass, (char *) bb, (intn) uint16var + 1);
1085               bb += (size_t)uint16var;
1086 	  }
1087 
1088           UINT16DECODE(bb, vg->extag);  /* retrieve the vg's expansion tag */
1089           UINT16DECODE(bb, vg->exref);  /* retrieve the vg's expansion ref */
1090 
1091           if (vg->version == VSET_NEW_VERSION)
1092             {
1093                 UINT32DECODE(bb, vg->flags);  /* retrieve new features in
1094                                                version 4, or higher */
1095                 if (vg->flags & VG_ATTR_SET)
1096                   {   /* the vg has attrs */
1097                       INT32DECODE(bb, vg->nattrs);
1098 
1099                       if (NULL == (vg->alist = HDmalloc(vg->nattrs * sizeof(vg_attr_t))))
1100                           HGOTO_ERROR(DFE_NOSPACE, FAIL);
1101 
1102                       for (i = 0; i < vg->nattrs; i++)
1103                         {
1104                             UINT16DECODE(bb, vg->alist[i].atag);
1105                             UINT16DECODE(bb, vg->alist[i].aref);
1106                         } /* for */
1107                   }  /* attributes set */
1108             }  /* new version */
1109       }     /* end if */
1110 done:
1111     if (ret_value == FAIL)
1112     { /* Error condition cleanup */
1113 
1114     } /* end if */
1115 
1116   /* Normal function cleanup */
1117   return ret_value;
1118 
1119 }   /* vunpackvg */
1120 
1121 /*******************************************************************************
1122  NAME
1123     VPgetinfo  --  Read in the "header" information about the Vgroup.
1124 
1125  DESCRIPTION
1126     This routine pre-reads the header information for a Vgroup into memory
1127     so that it can be accessed more quickly by the routines that need it.
1128 
1129  RETURNS
1130     Return a pointer to a VGROUP filled with the Vgroup information on success,
1131     NULL on failure.
1132 *******************************************************************************/
1133 VGROUP *
VPgetinfo(HFILEID f,uint16 ref)1134 VPgetinfo(HFILEID f,  /* IN: file handle */
1135           uint16 ref  /* IN: ref of vgroup */)
1136 {
1137     VGROUP         *vg = NULL;
1138 /*  intn          len;    intn mismatches Vgbufsize type -- uint32 */
1139     size_t          len;
1140     VGROUP *ret_value = NULL; /* FAIL */
1141     CONSTR(FUNC, "VPgetinfo");
1142 
1143     /* clear error stack */
1144     HEclear();
1145 
1146     /* Find out how long the VGroup information is */
1147     if (( len = Hlength(f, DFTAG_VG, (uint16) ref)) == FAIL)
1148         HGOTO_ERROR(DFE_INTERNAL,NULL);
1149 
1150     if(len > Vgbufsize)
1151       {
1152         Vgbufsize = len;
1153 
1154         if (Vgbuf)
1155             HDfree((VOIDP) Vgbuf);
1156 
1157         if ((Vgbuf = (uint8 *) HDmalloc(Vgbufsize)) == NULL)
1158             HGOTO_ERROR(DFE_NOSPACE, NULL);
1159       } /* end if */
1160 
1161     /* Get the raw Vgroup info */
1162     if (Hgetelement(f, DFTAG_VG, (uint16)ref, Vgbuf) == (int32)FAIL)
1163         HGOTO_ERROR(DFE_NOMATCH,NULL);
1164 
1165     /* allocate space for vg */
1166     if (NULL == (vg =VIget_vgroup_node()))
1167         HGOTO_ERROR(DFE_NOSPACE,NULL);
1168 
1169     /* unpack vgpack into structure vg, and init  */
1170     vg->f             = f;
1171     vg->oref          = ref;
1172     vg->otag          = DFTAG_VG;
1173     if (FAIL == vunpackvg(vg,Vgbuf,len))
1174          HGOTO_ERROR(DFE_INTERNAL, NULL);
1175 
1176     /* return vgroup */
1177     ret_value = vg;
1178 
1179 done:
1180   if(ret_value == NULL)
1181     { /* Error condition cleanup */
1182 
1183     } /* end if */
1184 
1185   /* Normal function cleanup */
1186 
1187   return ret_value;
1188 } /* end VPgetinfo */
1189 
1190 /*******************************************************************************
1191 NAME
1192   Vattach:
1193 
1194 DESCRIPTION
1195    attaches to an existing vgroup or creates a new vgroup.
1196    returns NULL if  error, else ptr to vgroup.
1197 
1198    IGNORE accesstype. (but save it)
1199 
1200    if vgid == -1,
1201      create a NEW vg if vgdir is not full.
1202      Also set nattach =1, nentries=0.
1203    if vgid +ve,
1204         look in vgdir to see if already attached,
1205          if yes, incr nattach
1206          if not, fetch from file. attach, set nattach=1, netries= val from file
1207 
1208        In any case, set marked flag to 0.
1209 
1210 RETRUNS
1211      SUCCEED/FAIL
1212 
1213 *******************************************************************************/
1214 int32
Vattach(HFILEID f,int32 vgid,const char * accesstype)1215 Vattach(HFILEID f,             /* IN: file handle */
1216         int32 vgid,            /* IN: vgroup id */
1217         const char *accesstype /* IN: access type */)
1218 {
1219     VGROUP     *vg = NULL;
1220     vginstance_t *v = NULL;
1221     vfile_t    *vf = NULL;
1222     filerec_t  *file_rec = NULL;       /* file record */
1223     int16       acc_mode;
1224     atom_t      ret_value = FAIL;
1225     CONSTR(FUNC, "Vattach");
1226 
1227     /* clear error stack */
1228     HEclear();
1229 
1230     /* check file id */
1231     if (f == FAIL)
1232         HGOTO_ERROR(DFE_ARGS, FAIL);
1233 
1234     /* get Vxxx file record */
1235     if ((vf = Get_vfile(f))==NULL)
1236         HGOTO_ERROR(DFE_FNF, FAIL);
1237 
1238     /* check access type to vgroup */
1239     if (accesstype[0] == 'R' || accesstype[0]=='r')
1240         acc_mode = 'r';
1241     else if (accesstype[0] == 'W' || accesstype[0]=='w')
1242         acc_mode = 'w';
1243     else
1244         HGOTO_ERROR(DFE_BADACC, FAIL);
1245 
1246     /* convert file id to file record and check for write-permission */
1247     file_rec = HAatom_object(f);
1248     if((file_rec==NULL || acc_mode=='w') && !(file_rec->access&DFACC_WRITE))
1249         HGOTO_ERROR(DFE_BADACC, FAIL);
1250 
1251     if (vgid == -1)
1252       {
1253           /******* create a NEW vg in vgdir ******/
1254           if (acc_mode == 'r')
1255               HGOTO_ERROR(DFE_ARGS, FAIL);
1256 
1257           /* allocate space for vg, & zero it out */
1258           if ((vg = VIget_vgroup_node()) == NULL)
1259               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1260 
1261           /* initialize new vg */
1262           vg->msize = MAXNVELT;
1263           vg->tag = (uint16 *) HDmalloc(vg->msize * sizeof(uint16));
1264           vg->ref = (uint16 *) HDmalloc(vg->msize * sizeof(uint16));
1265 
1266 	  vg->vgname = NULL;
1267 	  vg->vgclass = NULL;
1268 
1269           if ((vg->tag == NULL) || (vg->ref == NULL))
1270               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1271 
1272           vg->f = f;
1273           vg->otag = DFTAG_VG;
1274           vg->oref = Hnewref(f);    /* create a new unique ref for it */
1275           if (vg->oref == 0)
1276               HGOTO_ERROR(DFE_NOREF, FAIL);
1277 
1278           vg->access = (intn)acc_mode;
1279 
1280           vg->marked = 1;
1281 
1282 	  /* number of old-style attributes and list of their refs, these
1283 	     are only used when Vnoldattrs is invoked; see Vnoldattrs func
1284 	     header for info. 2/4/2011 -BMR */
1285           vg->old_alist = NULL;
1286           vg->noldattrs = 0;
1287 
1288           vg->new_vg = 1;
1289           vg->version = VSET_VERSION;
1290 
1291           /* attach new vg to file's vgtab  */
1292           if (NULL == (v = VIget_vginstance_node()))
1293               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1294 
1295           vf->vgtabn++;
1296           v->key = (int32) vg->oref;  /* set the key for the node */
1297           v->ref = (uintn)vg->oref;
1298           v->vg = vg;
1299           v->nattach = 1;
1300           tbbtdins(vf->vgtree, (VOIDP) v, NULL);    /* insert the vg instance in B-tree */
1301 
1302           ret_value=HAregister_atom(VGIDGROUP,v);
1303       }
1304     else
1305       {
1306           /******* access an EXISTING vg *********/
1307           if (NULL == (v = vginst(f, (uint16) vgid)))
1308               HGOTO_ERROR(DFE_NOMATCH, FAIL);
1309 
1310           /* vg already attached.  inc nattach and return existing ptr */
1311           if (v->nattach > 0)
1312             {
1313                 v->vg->access = MAX(v->vg->access, acc_mode);
1314                 v->nattach++;
1315             }
1316           else
1317             {
1318               vg=v->vg;
1319               vg->access = (intn)acc_mode;
1320               vg->marked = 0;
1321 
1322 	      /* number of old-style attributes and list of their refs, these
1323 		 are only used when Vnoldattrs is invoked; see Vnoldattrs func
1324 		 header for info. 2/4/2011 -BMR */
1325               vg->old_alist = NULL;
1326               vg->noldattrs = 0;
1327 
1328               /* attach vg to file's vgtab at the vg instance v */
1329               v->nattach = 1;
1330               v->nentries = (int32)vg->nvelt;
1331             } /* end else */
1332 
1333           ret_value=HAregister_atom(VGIDGROUP,v);
1334       }
1335 
1336 done:
1337   if(ret_value == FAIL)
1338     { /* Error condition cleanup */
1339 
1340     } /* end if */
1341 
1342   /* Normal function cleanup */
1343   return ret_value;
1344 }   /* Vattach */
1345 
1346 /*******************************************************************************
1347 NAME
1348    Vdetach
1349 
1350 DESCRIPTION
1351    Detaches access to vg.
1352 
1353      if marked flag is 1, write out vg to file.
1354        if vg still has velts attached to it, cannot detach vg.
1355        decr  nattach. if (nattach is 0), free vg from vg instance.
1356        (check that no velts are still attached to vg before freeing)
1357 
1358      if attached with read access, just return.
1359 
1360     after detach, set marked flag to 0.
1361 
1362 RETURNS
1363    SUCCEED / FAIL
1364 
1365 *******************************************************************************/
1366 int32
Vdetach(int32 vkey)1367 Vdetach(int32 vkey /* IN: vgroup key */)
1368 {
1369     VGROUP       *vg = NULL;
1370     vginstance_t *v = NULL;
1371     int32       vgpacksize;
1372     int32      ret_value = SUCCEED;
1373     CONSTR(FUNC, "Vdetach");
1374 
1375     /* clear error stack */
1376     HEclear();
1377 
1378     /* check if vgroup is valid */
1379     if (HAatom_group(vkey) != VGIDGROUP)
1380         HGOTO_ERROR(DFE_ARGS, FAIL);
1381 
1382     /* get instance of vgroup */
1383     if (NULL == (v = (vginstance_t *)HAremove_atom(vkey)))
1384         HGOTO_ERROR(DFE_NOVS, FAIL);
1385 
1386     /* get vgroup itself and check it */
1387     vg = v->vg;
1388     if ((vg == NULL) || (vg->otag != DFTAG_VG))
1389         HGOTO_ERROR(DFE_ARGS, FAIL);
1390 
1391     /* Now, only update the Vgroup if it has actually changed. */
1392     /* Since only Vgroups with write-access are allowed to change, there is */
1393     /* no reason to check for access... (I hope) -QAK */
1394     if (vg->marked == 1)
1395       {
1396           size_t need, vgnamelen=0, vgclasslen=0;
1397 	  if (vg->vgname != NULL)
1398 	      vgnamelen = strlen(vg->vgname);
1399 
1400 	  if (vg->vgclass != NULL)
1401 	      vgclasslen = strlen(vg->vgclass);
1402 
1403           need = sizeof(VGROUP)
1404 		+ vgnamelen	/* vgname dynamic, vpackvg omits null */
1405 		+ vgclasslen	/* vgclass dynamic, vpackvg omits null */
1406 		+ (size_t)vg->nvelt*4 + (size_t)vg->nattrs*sizeof(vg_attr_t) + 1;
1407           if(need > Vgbufsize)
1408             {
1409                 Vgbufsize = need;
1410 
1411                 if (Vgbuf)
1412                     HDfree((VOIDP) Vgbuf);
1413 
1414                 if ((Vgbuf = (uint8 *) HDmalloc(Vgbufsize)) == NULL)
1415                     HGOTO_ERROR(DFE_NOSPACE, FAIL);
1416             } /* end if */
1417 
1418           if (FAIL == vpackvg(vg, Vgbuf, &vgpacksize))
1419               HGOTO_ERROR(DFE_INTERNAL, FAIL);
1420 
1421           /*
1422            *  If vgroup alreay exists, try to re-use the same
1423            *  tag/ref. This will cause the pointer to the original
1424            *  vgroup to be lost but this is okay.
1425            */
1426           if(!vg->new_vg)
1427             {
1428                 /* check if tag/ref exists in DD list already */
1429                 switch(HDcheck_tagref(vg->f, DFTAG_VG, vg->oref))
1430                   {
1431                   case 0: /* not found */
1432                       break;
1433                   case 1: /* found, reuse tag/ref */
1434                       if (HDreuse_tagref(vg->f, DFTAG_VG, vg->oref) == FAIL)
1435                           HGOTO_ERROR(DFE_INTERNAL, FAIL);
1436                       break;
1437                   case -1: /* error */
1438                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1439                   default: /* should never get here */
1440                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1441                   }
1442             }
1443 
1444           /* write out vgroup */
1445           if (Hputelement(vg->f, DFTAG_VG, vg->oref, Vgbuf, vgpacksize) == FAIL)
1446               HERROR(DFE_WRITEERROR);
1447 
1448           vg->marked = 0;
1449           vg->new_vg = 0;
1450       }
1451 
1452     /* Free the old-style attribute list and reset associated fields */
1453     if (vg->old_alist != NULL)
1454     {
1455 	HDfree((VOIDP) vg->old_alist);
1456 	vg->old_alist = NULL;
1457 	vg->noldattrs = 0;
1458     }
1459 
1460     v->nattach--;
1461 
1462 done:
1463   if(ret_value == FAIL)
1464     { /* Error condition cleanup */
1465 
1466     } /* end if */
1467 
1468   /* Normal function cleanup */
1469   return ret_value;
1470 }   /* Vdetach */
1471 
1472 /*******************************************************************************
1473 NAME
1474    Vinsert
1475 
1476 DESCRIPTION
1477    inserts a velt (vs or vg)  into a vg
1478 
1479    checks and prevents duplicate links.
1480 
1481    Since multiple files are now possible, check that both vg and velt
1482    are from the same file. else error.
1483 
1484 RETURNS
1485     RETURNS entry position within vg (0 or +ve) or FAIL on error.
1486 
1487 *******************************************************************************/
1488 int32
Vinsert(int32 vkey,int32 insertkey)1489 Vinsert(int32 vkey,      /* IN: vgroup key */
1490         int32 insertkey  /* IN: */)
1491 {
1492     VGROUP       *vg = NULL;
1493     vginstance_t *v = NULL;
1494     uint16      newtag = 0;
1495     uint16      newref = 0;
1496     int32       newfid;
1497     uintn       u;
1498     int32       ret_value = SUCCEED;
1499     CONSTR(FUNC, "Vinsert");
1500 
1501     /* clear error stack */
1502     HEclear();
1503 
1504     /* check to see if vgroup is valid */
1505     if (HAatom_group(vkey) != VGIDGROUP)
1506         HGOTO_ERROR(DFE_ARGS, FAIL);
1507 
1508     /* get instance of vgroup */
1509     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1510         HGOTO_ERROR(DFE_NOVS, FAIL);
1511 
1512     /* get vgroup itself and check it */
1513     vg = v->vg;
1514     if (vg == NULL)
1515         HGOTO_ERROR(DFE_BADPTR, FAIL);
1516 
1517     /* check write access */
1518     if (vg->otag != DFTAG_VG || vg->access != 'w')
1519         HGOTO_ERROR(DFE_ARGS, FAIL);
1520 
1521     newfid = FAIL;
1522     if (HAatom_group(insertkey) == VSIDGROUP)
1523       {   /* locate vs's index in vstab */
1524         vsinstance_t *w;
1525 
1526         if (NULL == (w = (vsinstance_t *) HAatom_object(insertkey)))
1527             HGOTO_ERROR(DFE_NOVS, FAIL);
1528 
1529         if (w->vs == NULL)
1530             HGOTO_ERROR(DFE_ARGS, FAIL);
1531 
1532         newtag = DFTAG_VH;
1533         newref = w->vs->oref;
1534         newfid = w->vs->f;
1535       }
1536     else
1537       {
1538         vginstance_t *x;
1539 
1540         if (HAatom_group(insertkey) == VGIDGROUP)
1541           {   /* locate vs's index in vgtab */
1542             if (NULL == (x = (vginstance_t *) HAatom_object(insertkey)))
1543                 HGOTO_ERROR(DFE_NOVS, FAIL);
1544 
1545             if (x->vg == NULL)
1546                 HGOTO_ERROR(DFE_ARGS, FAIL);
1547 
1548             newtag = DFTAG_VG;
1549             newref = x->vg->oref;
1550             newfid = x->vg->f;
1551           }
1552       }
1553 
1554     /* make sure we found something */
1555     if (newfid == FAIL)
1556         HGOTO_ERROR(DFE_ARGS, FAIL);
1557 
1558     if (vg->f != newfid)
1559         HGOTO_ERROR(DFE_DIFFFILES, FAIL);
1560 
1561     /* check and prevent duplicate links */
1562     for (u = 0; u < (uintn)vg->nvelt; u++)
1563       {
1564         if ((vg->ref[u] == newref) && (vg->tag[u] == newtag))
1565             HGOTO_ERROR(DFE_DUPDD, FAIL);
1566       }
1567 
1568     /* Finally, ok to insert */
1569     if (vinsertpair(vg, newtag, newref) == FAIL)
1570         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1571 
1572     ret_value = (vg->nvelt - 1);
1573 
1574 done:
1575   if(ret_value == FAIL)
1576     { /* Error condition cleanup */
1577 
1578     } /* end if */
1579 
1580   /* Normal function cleanup */
1581   return ret_value;
1582 }   /* Vinsert */
1583 
1584 /*******************************************************************************
1585 NAME
1586   Vflocate
1587 
1588 DESCRIPTION
1589    Checks to see if the given field exists in a vdata belonging to this vgroup.
1590 
1591    28-MAR-91 Jason Ng NCSA
1592 
1593 RETURNS
1594    If found, returns the ref of the vdata.
1595    If not found, or error, returns FAIL
1596 
1597 *******************************************************************************/
1598 int32
Vflocate(int32 vkey,char * field)1599 Vflocate(int32 vkey,  /* IN: vdata key */
1600          char *field  /* IN: field to locate */)
1601 {
1602     uintn u;
1603     vginstance_t *v = NULL;
1604     VGROUP       *vg = NULL;
1605     int32       vskey;
1606     int32       ret_value = SUCCEED;
1607     CONSTR(FUNC, "Vflocate");
1608 
1609     /* clear error stack */
1610     HEclear();
1611 
1612     /* check if vgroup is valid */
1613     if (HAatom_group(vkey) != VGIDGROUP)
1614         HGOTO_ERROR(DFE_ARGS, FAIL);
1615 
1616     /* get instance of vgroup */
1617     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1618         HGOTO_ERROR(DFE_NOVS, FAIL);
1619 
1620     /* get vgroup itself and check */
1621     vg = v->vg;
1622     if (vg == NULL)
1623         HGOTO_ERROR(DFE_BADPTR, FAIL);
1624 
1625     for (u = 0; u < (uintn)vg->nvelt; u++)
1626       {
1627           intn       s;
1628 
1629           if (vg->tag[u] != VSDESCTAG)
1630               continue;
1631 
1632           vskey = VSattach(vg->f, (int32)vg->ref[u], "r");
1633           if (vskey == FAIL)
1634               HGOTO_DONE(FAIL);
1635 
1636           s = VSfexist(vskey, field);
1637 
1638           if (VSdetach(vskey) == FAIL)
1639               HGOTO_ERROR(DFE_INTERNAL, FAIL);
1640 
1641           if (s == 1)
1642               HGOTO_DONE((int32)vg->ref[u]);  /* found. return vdata's ref */
1643       }
1644 
1645     ret_value = (FAIL);  /* field not found */
1646 
1647 done:
1648   if(ret_value == FAIL)
1649     { /* Error condition cleanup */
1650 
1651     } /* end if */
1652 
1653   /* Normal function cleanup */
1654 
1655   return ret_value;
1656 }   /* Vflocate */
1657 
1658 /*******************************************************************************
1659 NAME
1660    Vinqtagref
1661 
1662 DESCRIPTION
1663     Checks whether the given tag/ref pair already exists in the vgroup.
1664     28-MAR-91 Jason Ng NCSA
1665 
1666 RETURNS
1667     RETURNS TRUE if exist
1668     RETURNS FALSE if not.
1669 
1670 *******************************************************************************/
1671 intn
Vinqtagref(int32 vkey,int32 tag,int32 ref)1672 Vinqtagref(int32 vkey, /* IN: vgroup key */
1673            int32 tag,  /* IN: tag to check in vgroup */
1674            int32 ref   /* IN: ref to check in vgroup */)
1675 {
1676     uintn u;
1677     uint16 ttag;
1678     uint16 rref;
1679     vginstance_t *v = NULL;
1680     VGROUP       *vg = NULL;
1681     intn       ret_value = FALSE;
1682     CONSTR(FUNC, "Vinqtagref");
1683 
1684     /* clear error stack */
1685     HEclear();
1686 
1687     /* check if vgroup is valid */
1688     if (HAatom_group(vkey) != VGIDGROUP)
1689         HGOTO_ERROR(DFE_ARGS, FALSE);
1690 
1691     /* get instance of vgroup */
1692     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1693         HGOTO_ERROR(DFE_NOVS, FALSE);
1694 
1695     /* get vgroup itself and check */
1696     vg = v->vg;
1697     if (vg == NULL)
1698         HGOTO_ERROR(DFE_BADPTR, FALSE);
1699 
1700     ttag = (uint16) tag;
1701     rref = (uint16) ref;
1702 
1703     for (u = 0; u < (uintn)vg->nvelt; u++)
1704       {
1705         if ((ttag == vg->tag[u]) && (rref == vg->ref[u]))
1706           HGOTO_DONE(TRUE);
1707       }
1708 
1709 done:
1710   if(ret_value == FALSE)
1711     { /* Error condition cleanup */
1712 
1713     } /* end if */
1714 
1715   /* Normal function cleanup */
1716   return ret_value;
1717 }   /* Vinqtagref */
1718 
1719 /*******************************************************************************
1720  NAME
1721    Vdeletetagref - delete tag/ref pair in Vgroup
1722 
1723  DESCRIPTION
1724     Deletes the given tag/ref pair from the Vgroup.  If the given tag/ref pair
1725     does not exist in the vgroup the routine will return FAIL. Users should use
1726     Vinqtagref() to check if the tag/ref pair exists before deleting.
1727 
1728  RETURNS
1729     Returns SUCCEED if the tag/ref pair is deleted from Vgroup and
1730     FAIL if unsuccessful.
1731 
1732  Author -GeorgeV 10/10/97
1733 *******************************************************************************/
1734 intn
Vdeletetagref(int32 vkey,int32 tag,int32 ref)1735 Vdeletetagref(int32 vkey, /* IN: vgroup key */
1736               int32 tag,  /* IN: tag to delete in vgroup */
1737               int32 ref   /* IN: ref to delete in vgroup */)
1738 {
1739     uintn         i,j;       /* loop indices */
1740     uint16        ttag;      /* tag for comparison */
1741     uint16        rref;      /* ref for comparison */
1742     vginstance_t *v  = NULL; /* vgroup instance struct */
1743     VGROUP       *vg = NULL; /* in-memory vgroup struct */
1744     intn          ret_value = SUCCEED;
1745     CONSTR(FUNC, "Vdeletetagref");
1746 
1747    /* NOTE: Move the following comments to the DESCRIPTION of the
1748             fcn when the issue with duplicate tag/refs is decided.
1749 
1750     If duplicate tag/ref pairs exist, then it deletes the first occurence.
1751     If the case of duplicate tag/ref pairs the user can call Vinqtagref()
1752     to see if there are more occurences and then delete them. */
1753 
1754     /* clear error stack */
1755     HEclear();
1756 
1757     /* check if vgroup is valid */
1758     if (HAatom_group(vkey) != VGIDGROUP)
1759         HGOTO_ERROR(DFE_ARGS, FAIL);
1760 
1761     /* get instance of vgroup */
1762     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1763         HGOTO_ERROR(DFE_NOVS, FAIL);
1764 
1765     /* get vgroup itself and check */
1766     vg = v->vg;
1767     if (vg == NULL)
1768         HGOTO_ERROR(DFE_BADPTR, FAIL);
1769 
1770     /* set comparsion tag/ref pair */
1771     ttag = (uint16) tag;
1772     rref = (uint16) ref;
1773 
1774     /* look through elements in vgroup */
1775     for (i = 0; i < (uintn)vg->nvelt; i++)
1776       { /* see if element tag/ref matches search tag/ref */
1777           if ((ttag == vg->tag[i]) && (rref == vg->ref[i]))
1778             { /* found tag/ref pair to delete.
1779                  If duplicate tag/ref pairs exist, then it deletes
1780                  the first occurence. If the case of duplicate tag/ref
1781                  pairs the user can call Vinqtagref() to see if there
1782                  are more occurences and then delete them.*/
1783 
1784                 /* check if element found is last one in vgroup */
1785                 if ( i != ((uintn)vg->nvelt - 1))
1786                   { /* Basically shifts the contents of the array down by one.
1787                        This method will preserve the order without using
1788                        extra memory for storage etc. If speed/performance
1789                        is an issue you can use memove()/memcpy(). */
1790                       for (j = i; j < (uintn)vg->nvelt - 1; j++)
1791                         {
1792                             vg->tag[j] = vg->tag[j+1];
1793                             vg->ref[j] = vg->ref[j+1];
1794                         }
1795 #if 0
1796                       /* This method is quick but does not preserve the
1797                          order of elements in a vgroup.
1798                          swap i'th element with last one. */
1799                       vg->tag[i] = vg->tag[(uintn)vg->nvelt - 1];
1800                       vg->ref[i] = vg->ref[(uintn)vg->nvelt - 1];
1801 #endif
1802 
1803                   }
1804                 /* else if last one , do nothing and allow the
1805                    number of elements to be decrementd. */
1806 
1807                 /* reset last ones, just to be sure  */
1808                 vg->tag[(uintn)vg->nvelt - 1] = DFTAG_NULL;
1809                 vg->ref[(uintn)vg->nvelt - 1] = 0; /* invalid ref */
1810 
1811                 vg->nvelt--; /* decrement number of elements in vgroup */
1812                 vg->marked = TRUE; /* mark vgroup as changed.
1813                                       forces re-writing of new vgroup. */
1814                 ret_value = SUCCEED;
1815                 goto done; /* we are done */
1816             } /* if found */
1817       } /* for all items in vgroup */
1818 
1819     /* reaching here means tag/ref pair not found. The user
1820        should have used Vinqtagref() before calling this fcn.
1821        Oh well...*/
1822     ret_value = FAIL;
1823 
1824 done:
1825   if(ret_value == FAIL)
1826     { /* Error condition cleanup */
1827 
1828     } /* end if */
1829 
1830   /* Normal function cleanup */
1831   return ret_value;
1832 }   /* Vdeletetagref */
1833 
1834 /*******************************************************************************
1835 NAME
1836    Vntagrefs
1837 
1838 DESCRIPTION
1839     Returns the number (0 or +ve integer) of tag/ref pairs in a vgroup.
1840     If error, returns FAIL
1841     28-MAR-91 Jason Ng NCSA.
1842 
1843 RETURNS
1844 
1845 *******************************************************************************/
1846 int32
Vntagrefs(int32 vkey)1847 Vntagrefs(int32 vkey /* IN: vgroup key */)
1848 {
1849     vginstance_t *v = NULL;
1850     VGROUP       *vg = NULL;
1851     int32      ret_value = SUCCEED;
1852     CONSTR(FUNC, "Vntagrefs");
1853 
1854     /* clear error stack */
1855     HEclear();
1856 
1857     /* check if vgroup is valid */
1858     if (HAatom_group(vkey)!=VGIDGROUP)
1859         HGOTO_ERROR(DFE_ARGS, FAIL);
1860 
1861     /* get instance of vgroup */
1862     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1863         HGOTO_ERROR(DFE_NOVS, FAIL);
1864 
1865     /* get vgroup itself and check */
1866     vg = v->vg;
1867     if (vg == NULL)
1868         HGOTO_ERROR(DFE_BADPTR, FAIL);
1869 
1870     ret_value = ((vg->otag == DFTAG_VG) ? (int32) vg->nvelt : FAIL);
1871 
1872 done:
1873   if(ret_value == FAIL)
1874     { /* Error condition cleanup */
1875 
1876     } /* end if */
1877 
1878   /* Normal function cleanup */
1879   return ret_value;
1880 }   /* Vntagrefs */
1881 
1882 /*******************************************************************************
1883 NAME
1884    Vnrefs
1885 
1886 DESCRIPTION
1887    Returns the number (0 or +ve integer) of tags of a given type in a vgroup.
1888    If error, returns FAIL
1889    05-NOV-94 Quincey Koziol.
1890 
1891 RETURNS
1892 
1893 *******************************************************************************/
1894 int32
Vnrefs(int32 vkey,int32 tag)1895 Vnrefs(int32 vkey, /* IN: vgroup key */
1896        int32 tag   /* IN: tag to find refs for */)
1897 {
1898     vginstance_t *v = NULL;
1899     VGROUP       *vg = NULL;
1900     uint16 ttag = (uint16)tag;    /* alias for faster comparison */
1901     uintn u;                    /* local counting variable */
1902     int32     ret_value = 0;   /* zero refs to start */
1903     CONSTR(FUNC, "Vnrefs");
1904 
1905     /* clear error stack */
1906     HEclear();
1907 
1908     /* check if vgroup is valid */
1909     if (HAatom_group(vkey) != VGIDGROUP)
1910         HGOTO_ERROR(DFE_ARGS, FAIL);
1911 
1912     /* get instance of vgroup */
1913     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1914         HGOTO_ERROR(DFE_NOVS, FAIL);
1915 
1916     /* get vgroup itself and check it */
1917     vg = v->vg;
1918     if (vg == NULL)
1919         HGOTO_ERROR(DFE_BADPTR, FAIL);
1920 
1921     for (u = 0; u < (uintn)vg->nvelt; u++)
1922       {
1923         if (ttag == vg->tag[u])
1924             ret_value++;
1925       }
1926 
1927 done:
1928   if(ret_value == FAIL)
1929     { /* Error condition cleanup */
1930 
1931     } /* end if */
1932 
1933   /* Normal function cleanup */
1934 
1935   return ret_value;
1936 }   /* Vnrefs */
1937 
1938 /*******************************************************************************
1939 NAME
1940    Vgettagrefs
1941 
1942 DESCRIPTION
1943     Returns n tag/ref pairs from the vgroup into the caller-supplied arrays
1944     tagrarray and refarray.
1945     n can be any +ve number, but arrays must be this big.
1946     28-MAR-91 Jason Ng NCSA.
1947 
1948     NOTE: Do not confuse with Vgettagref().
1949 
1950 RETURNS
1951     The total number of (0 or +ve #)  tag/ref pairs returned.
1952 
1953 *******************************************************************************/
1954 int32
Vgettagrefs(int32 vkey,int32 tagarray[],int32 refarray[],int32 n)1955 Vgettagrefs(int32 vkey,       /* IN: vgroup key */
1956             int32 tagarray[], /* IN/OUT: tag array to fill */
1957             int32 refarray[], /* IN/OUT: ref array to fill */
1958             int32 n           /* IN: number of pairs to return */)
1959 {
1960     int32       i;
1961     vginstance_t *v = NULL;
1962     VGROUP       *vg = NULL;
1963     int32      ret_value = SUCCEED;
1964     CONSTR(FUNC, "Vgettagrefs");
1965 
1966     /* clear error stack */
1967     HEclear();
1968 
1969     /* check if vgroup is valid */
1970     if (HAatom_group(vkey)!=VGIDGROUP)
1971         HGOTO_ERROR(DFE_ARGS, FAIL);
1972 
1973     /* get instance of vgroup */
1974     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
1975         HGOTO_ERROR(DFE_NOVS, FAIL);
1976 
1977     /* get vgroup itself and check */
1978     vg = v->vg;
1979     if (vg == NULL)
1980         HGOTO_ERROR(DFE_BADPTR, FAIL);
1981 
1982     if (n > (int32) vg->nvelt)
1983         n = (int32)vg->nvelt;
1984 
1985     for (i = 0; i < n; i++)
1986       {
1987           tagarray[i] = (int32) vg->tag[i];
1988           refarray[i] = (int32) vg->ref[i];
1989       }
1990 
1991     ret_value = (n);
1992 
1993 done:
1994   if(ret_value == FAIL)
1995     { /* Error condition cleanup */
1996 
1997     } /* end if */
1998 
1999   /* Normal function cleanup */
2000   return ret_value;
2001 }   /* Vgettagrefs */
2002 
2003 /*******************************************************************************
2004 NAME
2005    Vgettagref
2006 
2007 DESCRIPTION
2008    Returns a specified tag/ref pair from the vgroup.
2009    User specifies an index.
2010    12-MAY-91 Jason Ng NCSA.
2011 
2012    NOTE: Do not confuse with Vgettagrefs().
2013 
2014 RETURNS
2015    RETURNS FAIL if OK.
2016    RETURNS SUCCEED if error.
2017 
2018 *******************************************************************************/
2019 intn
Vgettagref(int32 vkey,int32 which,int32 * tag,int32 * ref)2020 Vgettagref(int32 vkey,   /* IN: vgroup key */
2021            int32 which,  /* IN: hmm */
2022            int32 *tag,   /* IN/OUT: tag to return */
2023            int32 *ref    /* IN/OUT: ref to return */)
2024 {
2025     vginstance_t *v = NULL;
2026     VGROUP       *vg = NULL;
2027     intn       ret_value = SUCCEED;
2028     CONSTR(FUNC, "Vgettagref");
2029 
2030     /* clear error stack */
2031     HEclear();
2032 
2033     /* check if vgroup is valid */
2034     if (HAatom_group(vkey) != VGIDGROUP)
2035         HGOTO_ERROR(DFE_ARGS, FAIL);
2036 
2037     /* get instance of vgroup */
2038     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2039         HGOTO_ERROR(DFE_NOVS, FAIL);
2040 
2041     /* get vgroup itself and check */
2042     vg = v->vg;
2043     if (vg == NULL)
2044         HGOTO_ERROR(DFE_BADPTR, FAIL);
2045 
2046     if (which < 0 || which > (int32) (vg->nvelt - 1))
2047         HGOTO_ERROR(DFE_RANGE, FAIL);     /* range err */
2048 
2049     *tag = (int32) vg->tag[which];
2050     *ref = (int32) vg->ref[which];
2051 
2052 done:
2053   if(ret_value == FAIL)
2054     { /* Error condition cleanup */
2055 
2056     } /* end if */
2057 
2058   /* Normal function cleanup */
2059   return ret_value;
2060 }   /* Vgettagref */
2061 
2062 /*******************************************************************************
2063 NAME
2064    VQuerytag
2065 
2066 DESCRIPTION
2067   Return the tag of this Vgroup.
2068   Return 0 on failure
2069 
2070 RETURNS
2071 
2072 *******************************************************************************/
2073 int32
VQuerytag(int32 vkey)2074 VQuerytag(int32 vkey /* IN: vgroup key */)
2075 {
2076     vginstance_t *v = NULL;
2077     VGROUP       *vg = NULL;
2078     int32      ret_value = SUCCEED;
2079     CONSTR(FUNC, "Vgettagref");
2080 
2081     /* clear error stack */
2082     HEclear();
2083 
2084     /* check if vgroup is valid */
2085     if (HAatom_group(vkey)!=VGIDGROUP)
2086         HGOTO_ERROR(DFE_ARGS, FAIL);
2087 
2088     /* get instance of vgroup */
2089     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2090         HGOTO_ERROR(DFE_NOVS, FAIL);
2091 
2092     /* get vgroup itself and check */
2093     vg = v->vg;
2094     if (vg == NULL)
2095         HGOTO_ERROR(DFE_BADPTR, FAIL);
2096 
2097     ret_value = ((int32) vg->otag);
2098 
2099 done:
2100   if(ret_value == FAIL)
2101     { /* Error condition cleanup */
2102 
2103     } /* end if */
2104 
2105   /* Normal function cleanup */
2106 
2107   return ret_value;
2108 }   /* VQuerytag */
2109 
2110 /*******************************************************************************
2111 NAME
2112    VQueryref
2113 
2114 DESCRIPTION
2115    Return the ref of this Vgroup.
2116    Return FAIL on failure
2117 
2118 RETURN
2119 *******************************************************************************/
2120 int32
VQueryref(int32 vkey)2121 VQueryref(int32 vkey /* IN: vgroup id */)
2122 {
2123     vginstance_t *v = NULL;
2124     VGROUP       *vg = NULL;
2125     int32     ret_value = SUCCEED;
2126     CONSTR(FUNC, "Vgettagref");
2127 
2128     /* clear error stack */
2129     HEclear();
2130 
2131     /* check if vgroup is valid */
2132     if (HAatom_group(vkey)!=VGIDGROUP)
2133         HGOTO_ERROR(DFE_ARGS, FAIL);
2134 
2135     /* get instance of vgroup */
2136     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2137         HGOTO_ERROR(DFE_NOVS, FAIL);
2138 
2139     /* get vgroup itself and check */
2140     vg = v->vg;
2141     if (vg == NULL)
2142         HGOTO_ERROR(DFE_BADPTR, FAIL);
2143 
2144     ret_value = ((int32) vg->oref);
2145 
2146 done:
2147   if(ret_value == FAIL)
2148     { /* Error condition cleanup */
2149 
2150     } /* end if */
2151 
2152   /* Normal function cleanup */
2153 
2154   return ret_value;
2155 }   /* VQueryref */
2156 
2157 /*******************************************************************************
2158 NAME
2159   Vaddtagref
2160 
2161 DESCRIPTION
2162   Inserts a tag/ref pair into the attached vgroup vg.
2163   First checks that the tag/ref is unique. (6/20/96 Maybe the original
2164    design required the uniqueness. However, the current code allows
2165    duplication if NO_DUPLICATES is not defined. The SD interface needs
2166    this feature to create SDS's with duplicated dimensions. For example
2167    a 3D SDS has dimensions "time", "presure" and "presure".)
2168   If error, returns FAIL or tag/ref is not inserted.
2169   If OK, returns the total number of tag/refs in the vgroup (a +ve integer).
2170   28-MAR-91 Jason Ng NCSA.
2171 
2172 RETURNS
2173 
2174 *******************************************************************************/
2175 int32
Vaddtagref(int32 vkey,int32 tag,int32 ref)2176 Vaddtagref(int32 vkey, /* IN: vgroup key */
2177            int32 tag,  /* IN: tag to add */
2178            int32 ref   /* IN: ref to add */)
2179 {
2180     vginstance_t *v = NULL;
2181     VGROUP       *vg = NULL;
2182 #ifdef NO_DUPLICATES
2183     uintn        i;
2184 #endif /* NO_DUPLICATES */
2185     int32      ret_value = SUCCEED;
2186     CONSTR(FUNC, "Vaddtagref");
2187 
2188     /* clear error stack */
2189     HEclear();
2190 
2191     /* check if vgroup is valid */
2192     if (HAatom_group(vkey) != VGIDGROUP)
2193         HGOTO_ERROR(DFE_ARGS, FAIL);
2194 
2195     /* get instance of vgroup */
2196     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2197         HGOTO_ERROR(DFE_NOVS, FAIL);
2198 
2199     /* get vgroup itself and check */
2200     vg = v->vg;
2201     if (vg == NULL)
2202         HGOTO_ERROR(DFE_BADPTR, FAIL);
2203 
2204 #ifdef NO_DUPLICATES
2205     /* SD interface needs duplication if two dims have the same name.
2206        So, don't remove the ifdef/endif pair.   */
2207     /* make sure doesn't already exist in the Vgroup */
2208     for (i = 0; i < vg->nvelt; i++)
2209         if ((tag == vg->tag[i]) && (ref == vg->ref[i]))
2210             HGOTO_DONE(FAIL);
2211 #endif  /* NO_DUPLICATES  */
2212 
2213     ret_value = vinsertpair(vg, (uint16) tag, (uint16) ref);
2214 
2215 done:
2216   if(ret_value == FAIL)
2217     { /* Error condition cleanup */
2218 
2219     } /* end if */
2220 
2221   /* Normal function cleanup */
2222   return ret_value;
2223 }   /* Vaddtagref */
2224 
2225 /*******************************************************************************
2226 NAME
2227   vinsertpair
2228 
2229 DESCRIPTION
2230    Inserts a tag/ref pair into the attached vgroup vg.
2231    Expand the tag/ref space if necessary
2232 
2233 RETURNS
2234     Returns the total number of tag/refs in the vgroup.
2235 
2236 *******************************************************************************/
2237 int32
vinsertpair(VGROUP * vg,uint16 tag,uint16 ref)2238 vinsertpair(VGROUP * vg, /* IN: vgroup struct */
2239             uint16 tag,  /* IN: tag to insert */
2240             uint16 ref   /* IN: ref to insert */)
2241 {
2242     int32    ret_value = SUCCEED;
2243     CONSTR(FUNC, "vinsertpair");
2244 
2245     /* clear error stack */
2246     HEclear();
2247 
2248     if ((intn)vg->nvelt >= vg->msize)
2249       {
2250           vg->msize *= 2;
2251 
2252           vg->tag = (uint16 *) HDrealloc((VOIDP) vg->tag, vg->msize * sizeof(uint16));
2253           vg->ref = (uint16 *) HDrealloc((VOIDP) vg->ref, vg->msize * sizeof(uint16));
2254 
2255           if ((vg->tag == NULL) || (vg->ref == NULL))
2256               HGOTO_ERROR(DFE_NOSPACE, FAIL);
2257       }
2258 
2259     vg->tag[(uintn)vg->nvelt] = tag;
2260     vg->ref[(uintn)vg->nvelt] = ref;
2261     vg->nvelt++;
2262 
2263     vg->marked = TRUE;
2264     ret_value = ((int32) vg->nvelt);
2265 
2266 done:
2267   if(ret_value == FAIL)
2268     { /* Error condition cleanup */
2269 
2270     } /* end if */
2271 
2272   /* Normal function cleanup */
2273 
2274   return ret_value;
2275 } /* vinsertpair() */
2276 
2277 /*******************************************************************************
2278 NAME
2279    Ventries
2280 
2281 DESCRIPTION
2282     returns the no of entries (+ve integer) in the vgroup vgid.
2283     vgid must be an actual id
2284 
2285     undocumented
2286 
2287 RETURNS
2288     RETURNS FAIL if error
2289 
2290 *******************************************************************************/
2291 int32
Ventries(HFILEID f,int32 vgid)2292 Ventries(HFILEID f,  /* IN: file handle */
2293          int32 vgid  /* IN: vgroup id */)
2294 {
2295     vginstance_t *v = NULL;
2296     int32      ret_value = SUCCEED;
2297     CONSTR(FUNC, "Ventries");
2298 
2299     /* clear error stack */
2300     HEclear();
2301 
2302     /* check vgroup id? */
2303     if (vgid < 1)
2304         HGOTO_ERROR(DFE_ARGS, FAIL);
2305 
2306     if((v = vginst(f,(uint16)vgid))==NULL)
2307         HGOTO_ERROR(DFE_NOMATCH,FAIL);          /* error */
2308 
2309     if (v->vg != NULL)
2310         ret_value = (int32)v->vg->nvelt;
2311     else
2312         ret_value = FAIL;
2313 
2314 done:
2315   if(ret_value == FAIL)
2316     { /* Error condition cleanup */
2317 
2318     } /* end if */
2319 
2320   /* Normal function cleanup */
2321 
2322   return ret_value;
2323 }   /* Ventries */
2324 
2325 /*******************************************************************************
2326 NAME
2327    Vsetname
2328 
2329 DESCRIPTION
2330    gives a name to the VGROUP vg.
2331 
2332 RETURNS
2333     RETURN VALUES: SUCCEED for success, FAIL for failure (big suprise, eh?)
2334 
2335 *******************************************************************************/
2336 int32
Vsetname(int32 vkey,const char * vgname)2337 Vsetname(int32 vkey,         /* IN: vgroup key */
2338          const char *vgname  /* IN: name to set for vgroup */)
2339 {
2340     CONSTR(FUNC, "Vsetname");
2341     vginstance_t *v = NULL;
2342     VGROUP       *vg = NULL;
2343     size_t	  name_len;
2344     int32	  ret_value = SUCCEED;
2345 
2346     /* clear error stack */
2347     HEclear();
2348 
2349     /* check if vgroup is valid and if vgroup name is okay */
2350     if (HAatom_group(vkey) != VGIDGROUP || vgname == NULL)
2351         HGOTO_ERROR(DFE_ARGS, FAIL);
2352 
2353     /* get instance of vgroup */
2354     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2355         HGOTO_ERROR(DFE_NOVS, FAIL);
2356 
2357     /* get vgroup itself and check */
2358     vg = v->vg;
2359     if (vg == NULL || vg->access!='w')
2360         HGOTO_ERROR(DFE_BADPTR, FAIL);
2361 
2362     /* copy the name over; if name exists, overwrite it */
2363 
2364     name_len = HDstrlen(vgname); /* shortcut of length of the given name */
2365 
2366     /* if name exists, release it */
2367     if (vg->vgname != NULL) HDfree(vg->vgname);
2368 
2369     /* allocate space for new name */
2370     vg->vgname = (char *)HDmalloc(name_len+1);
2371 
2372     /* check for unsuccessful allocation */
2373     if (vg->vgname == NULL) HGOTO_ERROR(DFE_NOSPACE, FAIL);
2374 
2375     /* copy given name after allocation succeeded, with \0 terminated */
2376     HIstrncpy(vg->vgname, vgname, name_len+1);
2377 
2378     vg->marked = TRUE;
2379 
2380 done:
2381   if(ret_value == FAIL)
2382     { /* Error condition cleanup */
2383 
2384     } /* end if */
2385 
2386   /* Normal function cleanup */
2387   return ret_value;
2388 }   /* Vsetname */
2389 
2390 /*******************************************************************************
2391 NAME
2392    Vsetclass
2393 
2394 DESCRIPTION
2395     Assigns a class name to the VGROUP vg.
2396 
2397 RETURNS
2398     RETURN VALUES: SUCCEED for success, FAIL for failure
2399 
2400 MODIFICATION
2401     2010/01/26 No longer truncates classname to max length of VGNAMELENMAX.
2402 
2403 *******************************************************************************/
2404 int32
Vsetclass(int32 vkey,const char * vgclass)2405 Vsetclass(int32 vkey,          /* IN: vgroup key */
2406           const char *vgclass  /* IN: class to set for vgroup */)
2407 {
2408     CONSTR(FUNC, "Vsetclass");
2409     vginstance_t *v = NULL;
2410     VGROUP       *vg = NULL;
2411     size_t        classname_len;
2412     int32         ret_value = SUCCEED;
2413 
2414     /* clear error stack */
2415     HEclear();
2416 
2417     /* check if vgroup is valid */
2418     if (HAatom_group(vkey) != VGIDGROUP)
2419         HGOTO_ERROR(DFE_ARGS, FAIL);
2420 
2421     /* check if class is valid */
2422     if (vgclass == NULL)
2423         HGOTO_ERROR(DFE_ARGS, FAIL);
2424 
2425     /* get instance of vgroup */
2426     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2427         HGOTO_ERROR(DFE_NOVS, FAIL);
2428 
2429     /* get vgroup itself and check. Also check write access to vgroup  */
2430     vg = v->vg;
2431     if (vg == NULL || vg->access != 'w')
2432         HGOTO_ERROR(DFE_BADPTR, FAIL);
2433 
2434     /*
2435      * copy the class over; if class exists, overwrite it
2436      */
2437 
2438     classname_len = HDstrlen(vgclass); /* length of the given class name */
2439 
2440     /* if name exists, release it */
2441     if (vg->vgclass != NULL) HDfree(vg->vgclass);
2442 
2443     /* allocate space for new name */
2444     vg->vgclass = (char *)HDmalloc(classname_len+1);
2445 
2446     /* check for unsuccessful allocation */
2447     if (vg->vgclass == NULL) HGOTO_ERROR(DFE_NOSPACE, FAIL);
2448 
2449     /* copy given class name after allocation succeeded, with \0 terminated */
2450     HIstrncpy(vg->vgclass, vgclass, classname_len+1);
2451 
2452     vg->marked = TRUE;
2453 
2454 done:
2455   if(ret_value == FAIL)
2456     { /* Error condition cleanup */
2457 
2458     } /* end if */
2459 
2460   /* Normal function cleanup */
2461 
2462   return ret_value;
2463 }   /* Vsetclass */
2464 
2465 /*******************************************************************************
2466 NAME
2467    Visvg
2468 
2469 DESCRIPTION
2470    Tests if an entry in the vgroup vg is a VGROUP, given the entry's id.
2471 
2472 RETURNS
2473     RETURNS TRUE if so
2474     RETURNS FALSE if not, or if error
2475 
2476 *******************************************************************************/
2477 intn
Visvg(int32 vkey,int32 id)2478 Visvg(int32 vkey, /* IN: vgroup key */
2479       int32 id    /* IN: id of entry in vgroup */)
2480 {
2481     uintn        u;
2482     uint16       ID;
2483     vginstance_t *v = NULL;
2484     VGROUP       *vg = NULL;
2485     intn         ret_value = FALSE; /* initialize to FALSE */
2486     CONSTR(FUNC, "Visvg");
2487 
2488     /* clear error stack */
2489     HEclear();
2490 
2491     /* check if vgroup is valid */
2492     if (HAatom_group(vkey) != VGIDGROUP)
2493         HGOTO_ERROR(DFE_ARGS, FALSE);
2494 
2495     /* get instance of vgroup */
2496     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2497         HGOTO_ERROR(DFE_NOVS, FALSE);
2498 
2499     /* get vgroup itself and check */
2500     vg = v->vg;
2501     if (vg == NULL)
2502         HGOTO_ERROR(DFE_BADPTR, FALSE);
2503 
2504     ID = (uint16) id; /* cast 32bit ID to 16bit id */
2505 
2506     for (u = 0; u < (uintn)vg->nvelt; u++)
2507       {
2508         if (vg->ref[u] == ID &&     /* if the ids match, */
2509             vg->tag[u] == DFTAG_VG)     /* and it is a vgroup */
2510           {
2511                 HGOTO_DONE(TRUE);
2512           }
2513       }
2514 
2515 done:
2516   if(ret_value == FALSE)
2517     { /* Error condition cleanup */
2518 
2519     } /* end if */
2520 
2521   /* Normal function cleanup */
2522 
2523   return ret_value;
2524 }   /* Visvg */
2525 
2526 /*******************************************************************************
2527 NAME
2528    Visvs
2529 
2530 DESCRIPTION
2531    Checks if an id in a vgroup refers to a VDATA
2532 
2533 RETURNS
2534    RETURNS 1 if so
2535    RETURNS 0 if not, or if error.
2536 
2537 *******************************************************************************/
2538 intn
Visvs(int32 vkey,int32 id)2539 Visvs(int32 vkey, /* IN: vgroup key */
2540       int32 id    /* IN: id of entry in vgroup */)
2541 {
2542     intn         i;
2543     vginstance_t *v = NULL;
2544     VGROUP       *vg = NULL;
2545     intn         ret_value = FALSE; /* initialize to false */
2546     CONSTR(FUNC, "VSisvs");
2547 
2548     /* clear error stack */
2549     HEclear();
2550 
2551     /* check if vgroup is valid */
2552     if (HAatom_group(vkey) != VGIDGROUP)
2553         HGOTO_ERROR(DFE_ARGS, FALSE);
2554 
2555     /* get instance of vgroup */
2556     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2557         HGOTO_ERROR(DFE_NOVS, FALSE);
2558 
2559     /* get vgroup itself and check */
2560     vg = v->vg;
2561     if (vg == NULL)
2562         HGOTO_ERROR(DFE_BADPTR, FALSE);
2563 
2564     i = (intn)vg->nvelt;
2565     while (i)
2566       {
2567         if (vg->ref[--i] == (uint16) id && vg->tag[i] == VSDESCTAG)
2568           HGOTO_DONE(TRUE);
2569       }
2570 
2571 done:
2572   if(ret_value == FALSE)
2573     { /* Error condition cleanup */
2574 
2575     } /* end if */
2576 
2577   /* Normal function cleanup */
2578 
2579   return ret_value;
2580 }   /* Visvs */
2581 
2582 /*******************************************************************************
2583 NAME
2584    Vgetid
2585 
2586 DESCRIPTION
2587    Given a vgroup's id, returns the next vgroup's id in the file f .
2588    The call Vgetid(f,-1) returns the id of the FIRST vgroup in the file.
2589 
2590    This id is actually the "ref" of the vgroup "tag/ref".
2591 
2592 RETURNS
2593    RETURNS -1 if error
2594    RETURNS the next vgroup's id (0 or +ve integer).
2595 
2596 *******************************************************************************/
2597 int32
Vgetid(HFILEID f,int32 vgid)2598 Vgetid(HFILEID f,  /* IN: file handle */
2599        int32 vgid  /* IN: vgroup id */)
2600 {
2601     vginstance_t *v = NULL;
2602     vfile_t      *vf = NULL;
2603     VOIDP        *t = NULL;
2604     int32        key;
2605     int32        ret_value = SUCCEED;
2606     CONSTR(FUNC, "Vgetid");
2607 
2608 
2609     /* clear error stack */
2610     HEclear();
2611 
2612     /* check if vgroup id is valid */
2613     if (vgid < -1)
2614         HGOTO_ERROR(DFE_ARGS, FAIL);
2615 
2616     /* get vgroup file record */
2617     if (NULL == (vf = Get_vfile(f)))
2618         HGOTO_ERROR(DFE_FNF, FAIL);
2619 
2620     if (vgid == (-1))
2621       {     /* check for magic value to return the first group */
2622           if (vf->vgtree == NULL )
2623               HGOTO_DONE(FAIL); /* just return FAIL, no error */
2624 
2625           if (NULL == (t = (VOIDP *) tbbtfirst((TBBT_NODE *) * (vf->vgtree))))
2626               HGOTO_DONE(FAIL); /* just return FAIL, no error */
2627 
2628           /* t is assumed to valid at this point */
2629           v = (vginstance_t *) * t;   /* get actual pointer to the vginstance_t */
2630           HGOTO_DONE((int32)v->ref); /* rets 1st vgroup's ref */
2631       }
2632     else /* vgid >= 0 */
2633       {
2634           /* look in vgtab for vgid */
2635           /* tbbtdfind returns a pointer to the vginstance_t pointer */
2636           key = (int32)vgid;
2637           t = (VOIDP *) tbbtdfind(vf->vgtree, (VOIDP) &key, NULL);
2638 
2639           if (t == NULL ||
2640               t == (VOIDP *) tbbtlast((TBBT_NODE *) * (vf->vgtree)))
2641             { /* couldn't find the old vgid or at the end */
2642               ret_value = (FAIL);
2643             }
2644           else if (NULL == (t = (VOIDP *) tbbtnext((TBBT_NODE *) t))) /* get the next node in the tree */
2645               ret_value = (FAIL);
2646           else
2647             {
2648                 v = (vginstance_t *) * t;     /* get actual pointer to the vginstance_t */
2649                 ret_value = (int32)v->ref;  /* rets next vgroup's ref */
2650             }     /* end else */
2651       }
2652 done:
2653   if(ret_value == FAIL)
2654     { /* Error condition cleanup */
2655 
2656     } /* end if */
2657 
2658   /* Normal function cleanup */
2659 
2660   return ret_value;
2661 }   /* Vgetid */
2662 
2663 /*******************************************************************************
2664 NAME
2665    Vgetnext
2666 
2667 DESCRIPTION
2668    Given the id of an entry from a vgroup vg, looks in vg for the next
2669    entry after it, and returns its id.
2670    The call Vgetnext (vg,-1) returns the id of the FIRST entry in the vgroup.
2671 
2672    Vgetnext will look at only VSET elements in the vgroup.
2673    To look at all links in a vgroup, use Vgettagrefs instead.
2674 
2675   This id is actually the "ref" of the entry's "tag/ref".
2676 
2677 RETURNS
2678    RETURNS -1 if error
2679    RETURNS the id of the next entry( 0 or +ve integer)  in the vgroup.
2680 
2681 
2682 *******************************************************************************/
2683 int32
Vgetnext(int32 vkey,int32 id)2684 Vgetnext(int32 vkey, /* IN: vgroup key */
2685          int32 id    /* IN: id of entry in vgroup */)
2686 {
2687     uintn        u;
2688     vginstance_t *v = NULL;
2689     VGROUP       *vg = NULL;
2690     int32        ret_value = FAIL;
2691     CONSTR(FUNC, "Vgetnext");
2692 
2693     /* clear error stack */
2694     HEclear();
2695 
2696     /* check if vgroup is valid. Also check if 'id' is valid */
2697     if (HAatom_group(vkey) != VGIDGROUP || id < (-1))
2698         HGOTO_ERROR(DFE_ARGS, FAIL);
2699 
2700     /* get instance of vgroup */
2701     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2702         HGOTO_ERROR(DFE_NOVS, FAIL);
2703 
2704     /* get vgroup itself and check. */
2705     vg = v->vg;
2706     if ((vg == NULL) || (vg->otag != DFTAG_VG))
2707         HGOTO_ERROR(DFE_ARGS, FAIL);
2708 
2709     /* hmm..if no elements we return FAIL */
2710     if (vg->nvelt == 0)
2711         HGOTO_DONE(FAIL);
2712 
2713     /* if id is '-1' then the first entry in the vgroup is returned
2714        if it is a vgroup ? */
2715     if (id == -1)
2716       {
2717           if ((vg->tag[0] == DFTAG_VG) || (vg->tag[0] == VSDESCTAG))
2718               HGOTO_DONE((int32)vg->ref[0]);  /* id of first entry */
2719       }     /* end if */
2720 
2721     /* look in vgroup for 'id' */
2722     for (u = 0; u < (uintn)vg->nvelt; u++)
2723       { /* only look for vgroups? */
2724         if ((vg->tag[u] == DFTAG_VG) || (vg->tag[u] == VSDESCTAG))
2725           {
2726               if (vg->ref[u] == (uint16) id)
2727                 {
2728                     if (u == (uintn)(vg->nvelt - 1))
2729                       {
2730                         HGOTO_DONE(FAIL);
2731                       } /* end if */
2732                     else
2733                       {
2734                           if ((vg->tag[u + 1] == DFTAG_VG) || (vg->tag[u + 1] == VSDESCTAG))
2735                             {
2736                               HGOTO_DONE((int32)vg->ref[u + 1]);  /* return the id of next entry */
2737                             }
2738                           else
2739                             {
2740                               HGOTO_DONE(FAIL);
2741                             }
2742                       }     /* end else */
2743                 }   /* end if */
2744           }     /* end if */
2745       }
2746 
2747 done:
2748   if(ret_value == FAIL)
2749     { /* Error condition cleanup */
2750 
2751     } /* end if */
2752 
2753   /* Normal function cleanup */
2754 
2755   return ret_value;
2756 }   /* Vgetnext  */
2757 
2758 /*******************************************************************************
2759 NAME
2760    Vgetnamelen
2761 
2762 DESCRIPTION
2763    Retrieves the length of the vgroup's name.
2764 
2765 RETURNS
2766    Returns SUCCEED/FAIL
2767    BMR - 2006/09/10
2768 
2769 *******************************************************************************/
2770 int32
Vgetnamelen(int32 vkey,uint16 * name_len)2771 Vgetnamelen(int32 vkey,   /* IN: vgroup key */
2772 	    uint16 *name_len /* OUT: length of vgroup's name */)
2773 {
2774     vginstance_t *v = NULL;
2775     VGROUP       *vg = NULL;
2776     int32        ret_value = SUCCEED;
2777     CONSTR(FUNC, "Vgetnamelen");
2778 
2779 
2780     /* clear error stack */
2781     HEclear();
2782 
2783     /* check if vgroup is valid and the vgname */
2784     if (HAatom_group(vkey)!=VGIDGROUP)
2785         HGOTO_ERROR(DFE_ARGS, FAIL);
2786 
2787     /* get instance of vgroup */
2788     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2789         HGOTO_ERROR(DFE_NOVS, FAIL);
2790 
2791     /* get vgroup itself and check */
2792     vg = v->vg;
2793     if (vg == NULL)
2794         HGOTO_ERROR(DFE_BADPTR, FAIL);
2795 
2796     /*
2797      * Obtain the name length
2798      */
2799 
2800     /* if there is no name... */
2801     if (vg->vgname == NULL)
2802 	*name_len = 0;
2803     /* if name had been set... */
2804     else
2805     {
2806 	size_t temp_len = HDstrlen(vg->vgname); /* shortcut */
2807 
2808 	/* return name's length if it is a valid value */
2809 	if (temp_len >= 0)
2810             *name_len = (uint16)temp_len;
2811 	else /* unlikely, but just in case */
2812 	    ret_value = FAIL;
2813     }
2814 
2815 done:
2816   if(ret_value == FAIL)
2817     { /* Error condition cleanup */
2818 
2819     } /* end if */
2820   /* Normal function cleanup */
2821   return ret_value;
2822 }   /* Vgetnamelen */
2823 
2824 /*******************************************************************************
2825 NAME
2826    Vgetclassnamelen
2827 
2828 DESCRIPTION
2829    Retrieves the length of the vgroup's name.
2830 
2831 RETURNS
2832    Returns SUCCEED/FAIL
2833    BMR - 2006/09/10
2834 
2835 *******************************************************************************/
2836 int32
Vgetclassnamelen(int32 vkey,uint16 * classname_len)2837 Vgetclassnamelen(int32 vkey,   /* IN: vgroup key */
2838 	    uint16 *classname_len /* OUT: length of vgroup's classname */)
2839 {
2840     vginstance_t *v = NULL;
2841     VGROUP       *vg = NULL;
2842     size_t       temp_len;
2843     int32        ret_value = SUCCEED;
2844     CONSTR(FUNC, "Vgetclassnamelen");
2845 
2846 
2847     /* clear error stack */
2848     HEclear();
2849 
2850     /* check if vgroup is valid and the vgname */
2851     if (HAatom_group(vkey)!=VGIDGROUP)
2852         HGOTO_ERROR(DFE_ARGS, FAIL);
2853 
2854     /* get instance of vgroup */
2855     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2856         HGOTO_ERROR(DFE_NOVS, FAIL);
2857 
2858     /* get vgroup itself and check */
2859     vg = v->vg;
2860     if (vg == NULL)
2861         HGOTO_ERROR(DFE_BADPTR, FAIL);
2862 
2863     /* obtain the class name length */
2864     if (vg->vgclass == NULL)
2865 	*classname_len = 0;
2866     /* if name had been set... */
2867     else
2868     {
2869 	size_t temp_len = HDstrlen(vg->vgclass); /* shortcut */
2870 
2871 	/* return class name's length if it is a valid value */
2872 	if (temp_len >= 0)
2873             *classname_len = (uint16)temp_len;
2874 	else /* unlikely, but just in case */
2875 	    ret_value = FAIL;
2876     }
2877 
2878 done:
2879   if(ret_value == FAIL)
2880     { /* Error condition cleanup */
2881 
2882     } /* end if */
2883 
2884   /* Normal function cleanup */
2885 
2886   return ret_value;
2887 }   /* Vgetclassnamelen */
2888 
2889 /*******************************************************************************
2890 NAME
2891    Vgetname
2892 
2893 DESCRIPTION
2894    returns the vgroup's name
2895    ASSUME that vgname has been allocated large enough to hold
2896    the name
2897 
2898 RETURNS
2899    SUCCEED / FAIL
2900 
2901 *******************************************************************************/
2902 int32
Vgetname(int32 vkey,char * vgname)2903 Vgetname(int32 vkey,   /* IN: vgroup key */
2904          char *vgname  /* IN/OUT: vgroup name */)
2905 {
2906     vginstance_t *v = NULL;
2907     VGROUP       *vg = NULL;
2908     int32        ret_value = SUCCEED;
2909     CONSTR(FUNC, "Vgetname");
2910 
2911 
2912     /* clear error stack */
2913     HEclear();
2914 
2915     /* check if vgroup is valid and the vgname */
2916     if (HAatom_group(vkey)!=VGIDGROUP || vgname==NULL)
2917         HGOTO_ERROR(DFE_ARGS, FAIL);
2918 
2919     /* get instance of vgroup */
2920     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2921         HGOTO_ERROR(DFE_NOVS, FAIL);
2922 
2923     /* get vgroup itself and check */
2924     vg = v->vg;
2925     if (vg == NULL)
2926         HGOTO_ERROR(DFE_BADPTR, FAIL);
2927 
2928     /* copy vgroup name over if it had been set */
2929     if (vg->vgname != NULL)
2930 	HDstrcpy(vgname, vg->vgname);
2931     else
2932 	vgname[0] = '\0';
2933 
2934 done:
2935   if(ret_value == FAIL)
2936     { /* Error condition cleanup */
2937 
2938     } /* end if */
2939 
2940   /* Normal function cleanup */
2941 
2942   return ret_value;
2943 }   /* Vgetname */
2944 
2945 /*******************************************************************************
2946 NAME
2947    Vgetclass
2948 
2949 DESCRIPTION
2950    returns the vgroup's class name
2951    ASSUME that vgclass has been allocated large enough to hold
2952    the name
2953 
2954 RETURNS
2955    SUCCEED/FAIL
2956 
2957 *******************************************************************************/
2958 int32
Vgetclass(int32 vkey,char * vgclass)2959 Vgetclass(int32 vkey,    /* IN: vgroup key */
2960           char *vgclass  /* IN/OUT: vgroup class */)
2961 {
2962     vginstance_t *v = NULL;
2963     VGROUP       *vg = NULL;
2964     int32        ret_value = SUCCEED;
2965     CONSTR(FUNC, "Vgetclass");
2966 
2967 
2968     /* clear error stack */
2969     HEclear();
2970 
2971     /* check if vgroup is valid and also vgroup class */
2972     if (HAatom_group(vkey) != VGIDGROUP || vgclass==NULL)
2973         HGOTO_ERROR(DFE_ARGS, FAIL);
2974 
2975     /* get instance of vgroup */
2976     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
2977         HGOTO_ERROR(DFE_NOVS, FAIL);
2978 
2979     /* get vgroup itself and check */
2980     vg = v->vg;
2981     if (vg == NULL)
2982         HGOTO_ERROR(DFE_BADPTR, FAIL);
2983 
2984     /* copy class over if it had been set */
2985     if (vg->vgclass != NULL)
2986 	HDstrcpy(vgclass, vg->vgclass);
2987     else
2988 	vgclass[0] = '\0';
2989 
2990 done:
2991   if(ret_value == FAIL)
2992     { /* Error condition cleanup */
2993 
2994     } /* end if */
2995 
2996   /* Normal function cleanup */
2997 
2998   return ret_value;
2999 }   /* Vgetclass */
3000 
3001 /*******************************************************************************
3002 NAME
3003    Vinquire
3004 
3005 DESCRIPTION
3006    General inquiry routine for VGROUP.
3007    output parameters:
3008          nentries - no of entries in the vgroup
3009          vgname  - the vgroup's name
3010 
3011 RETURNS
3012    RETURNS FAIL if error
3013    RETURNS SUCCEED if ok
3014 
3015 *******************************************************************************/
3016 intn
Vinquire(int32 vkey,int32 * nentries,char * vgname)3017 Vinquire(int32 vkey,        /* IN: vgroup key */
3018          int32 *nentries,   /* IN/OUT: number of entries in vgroup */
3019          char *vgname       /* IN/OUT: vgroup name */)
3020 {
3021     vginstance_t *v = NULL;
3022     VGROUP       *vg = NULL;
3023     intn    ret_value = SUCCEED;
3024     CONSTR(FUNC, "Vinquire");
3025 
3026 
3027     /* clear error stack */
3028     HEclear();
3029 
3030     /* check if vgroup is valid */
3031     if (HAatom_group(vkey) != VGIDGROUP)
3032         HGOTO_ERROR(DFE_ARGS, FAIL);
3033 
3034     /* get instance of vgroup */
3035     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
3036         HGOTO_ERROR(DFE_NOVS, FAIL);
3037 
3038     /* get vgroup itself and check */
3039     vg = v->vg;
3040     if (vg == NULL)
3041         HGOTO_ERROR(DFE_BADPTR, FAIL);
3042 
3043     /* check tag of vgroup */
3044     if (vg->otag != DFTAG_VG)
3045         HGOTO_ERROR(DFE_ARGS, FAIL);
3046 
3047     /* copy vgroup name if requested.  Assumes 'vgname' has sufficient space */
3048     if (vgname != NULL)
3049         HDstrcpy(vgname, vg->vgname);
3050 
3051     /* set number of entries in vgroup if requested */
3052     if (nentries != NULL)
3053         *nentries = (int32)vg->nvelt;
3054 
3055 done:
3056   if(ret_value == FAIL)
3057     { /* Error condition cleanup */
3058 
3059     } /* end if */
3060 
3061   /* Normal function cleanup */
3062 
3063   return ret_value;
3064 }   /* Vinquire */
3065 
3066 
3067 /*******************************************************************************
3068 NAME
3069    Vopen
3070 
3071 DESCRIPTION
3072    This routine will replace the code segment " Hopen(); Vinitialize(f)".
3073    Thus, if Vopen is used, do not call Vinitialize after that.
3074 
3075    Similar to Hopen().
3076 
3077    This routine opens the HDF file and initializes it for Vset operations.
3078 
3079    See also Vclose().
3080 
3081    By: Jason Ng 10 Aug 92
3082 
3083 RETURNS
3084     RETURN VALUE:
3085     if error:  -1 (FAIL).
3086     if successful: the id of the file (>0).
3087 
3088 *******************************************************************************/
3089 HFILEID
Vopen(char * path,intn acc_mode,int16 ndds)3090 Vopen(char *path,     /* IN: file name */
3091       intn acc_mode,  /* IN: type of file access */
3092       int16 ndds      /* IN: number of DD in a block */)
3093 {
3094     HFILEID    ret_value=SUCCEED;
3095     CONSTR(FUNC, "Vopen");
3096 
3097     /* clear error stack */
3098     HEclear();
3099 
3100     /* use 'Hopen' to open file */
3101     if ((ret_value = Hopen(path, acc_mode, ndds))== FAIL)
3102       HGOTO_ERROR(DFE_BADOPEN,FAIL);
3103 
3104     /* Initialize Vxx interface */
3105     if(Vinitialize(ret_value)==FAIL)
3106       HGOTO_ERROR(DFE_CANTINIT,FAIL);
3107 
3108 done:
3109   if(ret_value == FAIL)
3110     { /* Error condition cleanup */
3111 
3112     } /* end if */
3113 
3114   /* Normal function cleanup */
3115 
3116   return ret_value;
3117 } /* Vopen() */
3118 
3119 /*******************************************************************************
3120 NAME
3121   Vclose
3122 
3123 DESCRIPTION
3124    This routine will replace the code segment " Vfinish(f); Hclose(f);".
3125    Thus, if Vclose is used, do not call Vfinish before that.
3126 
3127    This routine closes the HDF file, after it has freed all memory and
3128    updated the file.
3129 
3130    See also Vopen().
3131 
3132 RETURNS
3133    RETURN VALUE:  intn status - result of Hopen().
3134 
3135 *******************************************************************************/
3136 intn
Vclose(HFILEID f)3137 Vclose(HFILEID f /* IN: file handle */)
3138 {
3139 #ifdef LATER
3140     CONSTR(FUNC, "Vclose");
3141 #endif
3142     intn ret_value = SUCCEED;
3143 
3144     if (Vfinish(f) == FAIL)
3145         ret_value = FAIL;
3146     else
3147         ret_value = (Hclose(f));
3148 
3149     return ret_value;
3150 } /* Vclose() */
3151 
3152 /*******************************************************************************
3153 NAME
3154    Vdelete
3155 
3156 DESCRIPTION
3157    Remove a Vgroup from its file.  This function will both remove the Vgoup
3158    from the internal Vset data structures as well as from the file.
3159 
3160    'vgid' here is actually the ref of the Vgroup.
3161 
3162    (i.e. it calls tbbt_delete() and Hdeldd())
3163 
3164 RETURNS
3165    Return FAIL / SUCCEED
3166 
3167 *******************************************************************************/
3168 int32
Vdelete(int32 f,int32 vgid)3169 Vdelete(int32 f,     /* IN: file handle */
3170         int32 vgid   /* IN: vgroup id i.e. ref */)
3171 {
3172     VOIDP       v;
3173     vfile_t    *vf = NULL;
3174     VOIDP      *t = NULL;
3175     int32       key;
3176     filerec_t  *file_rec = NULL;       /* file record */
3177     int32       ret_value = SUCCEED;
3178     CONSTR(FUNC, "Vdelete");
3179 
3180     /* clear error stack */
3181     HEclear();
3182 
3183     /* check vgroup id is valid */
3184     if (vgid < 0)
3185         HGOTO_ERROR(DFE_ARGS, FAIL);
3186 
3187     /* convert file id to file record */
3188     if ((file_rec = HAatom_object(f)) == NULL)
3189         HGOTO_ERROR(DFE_BADACC, FAIL);
3190 
3191     /* check for write-permission to file*/
3192     if(!(file_rec->access & DFACC_WRITE))
3193         HGOTO_ERROR(DFE_BADACC, FAIL);
3194 
3195     /* get vgroup file record */
3196     if (NULL == (vf = Get_vfile(f)))
3197         HGOTO_ERROR(DFE_FNF, FAIL);
3198 
3199     /* find vgroup node in TBBT using it's ref */
3200     key = (int32)vgid;
3201     if (( t = (VOIDP *) tbbtdfind(vf->vgtree, (VOIDP) &key, NULL))== NULL)
3202       HGOTO_DONE(FAIL);
3203 
3204     /* remove vgroup node from TBBT */
3205     if((v = tbbtrem((TBBT_NODE **) vf->vgtree, (TBBT_NODE *) t, NULL))!=NULL)
3206         vdestroynode((VOIDP) v);
3207 
3208     /* Delete vgroup from file */
3209     if(Hdeldd(f, DFTAG_VG, (uint16) vgid) == FAIL)
3210         HGOTO_ERROR(DFE_INTERNAL, FAIL);
3211 
3212 done:
3213   if(ret_value == FAIL)
3214     { /* Error condition cleanup */
3215 
3216     } /* end if */
3217 
3218   /* Normal function cleanup */
3219 
3220   return ret_value;
3221 }   /* Vdelete */
3222 
3223 /*******************************************************************************
3224  NAME
3225     VIstart  --  V-level initialization routine
3226 
3227  DESCRIPTION
3228     Register the shut-down routines (VPshutdown & VSPshutdown) for call
3229     with atexit.
3230 
3231  RETURNS
3232     Returns SUCCEED/FAIL
3233 *******************************************************************************/
3234 PRIVATE intn
VIstart(void)3235 VIstart(void)
3236 {
3237     intn        ret_value = SUCCEED;
3238     CONSTR(FUNC, "VIstart");    /* for HERROR */
3239 
3240     /* Don't call this routine again... */
3241     library_terminate = TRUE;
3242 
3243     /* Install atexit() library cleanup routine */
3244     if (HPregister_term_func(&VPshutdown) != 0)
3245       HGOTO_ERROR(DFE_CANTINIT, FAIL);
3246 
3247     /* Install atexit() library cleanup routine */
3248     if (HPregister_term_func(&VSPshutdown) != 0)
3249       HGOTO_ERROR(DFE_CANTINIT, FAIL);
3250 
3251 done:
3252   if(ret_value == FAIL)
3253     { /* Error condition cleanup */
3254 
3255     } /* end if */
3256 
3257   /* Normal function cleanup */
3258 
3259     return(ret_value);
3260 } /* end VIstart() */
3261 
3262 /*******************************************************************************
3263  NAME
3264     VPshutdown  --  Terminate various static buffers.
3265 
3266  DESCRIPTION
3267     Free various buffers allocated in the V routines.
3268 
3269  RETURNS
3270     Returns SUCCEED/FAIL
3271 
3272 *******************************************************************************/
3273 intn
VPshutdown(void)3274 VPshutdown(void)
3275 {
3276     VGROUP       *v  = NULL;
3277     vginstance_t *vg = NULL;
3278     intn         ret_value = SUCCEED;
3279     CONSTR(FUNC, "VPshutdown");
3280 
3281     /* Release the vdata free-list if it exists */
3282     if(vgroup_free_list != NULL)
3283       {
3284           while(vgroup_free_list != NULL)
3285             {
3286                 v = vgroup_free_list;
3287                 vgroup_free_list = vgroup_free_list->next;
3288                 v->next = NULL;
3289                 HDfree(v);
3290             } /* end while */
3291       } /* end if */
3292 
3293     /* Release the vginstance free-list if it exists */
3294     if(vginstance_free_list != NULL)
3295       {
3296           while(vginstance_free_list != NULL)
3297             {
3298                 vg = vginstance_free_list;
3299                 vginstance_free_list = vginstance_free_list->next;
3300                 vg->next = NULL;
3301                 HDfree(vg);
3302             } /* end while */
3303       } /* end if */
3304 
3305     if(vtree != NULL)
3306       {
3307           /* Free the vfile tree */
3308           tbbtdfree(vtree, vfdestroynode, NULL);
3309 
3310           /* Destroy the atom groups for Vdatas and Vgroups */
3311           if (HAdestroy_group(VSIDGROUP) == FAIL)
3312               HGOTO_ERROR(DFE_INTERNAL, FAIL);
3313 
3314           if (HAdestroy_group(VGIDGROUP) == FAIL)
3315               HGOTO_ERROR(DFE_INTERNAL, FAIL);
3316 
3317           vtree = NULL;
3318       } /* end if */
3319 
3320     if(Vgbuf != NULL)
3321       {
3322           HDfree(Vgbuf);
3323           Vgbuf = NULL;
3324           Vgbufsize = 0;
3325       } /* end if */
3326 
3327 
3328 done:
3329   if(ret_value == FAIL)
3330     { /* Error condition cleanup */
3331 
3332     } /* end if */
3333 
3334   /* Normal function cleanup */
3335     return ret_value;
3336 } /* end VPshutdown() */
3337 
3338 
3339 /*******************************************************************************
3340  NAME
3341     Vgisinternal  --  Determine if a vgroup is internally created by the lib
3342  RETURNS
3343     Returns TRUE (1) if vkey is a vgroup that is internally created
3344     by the library, FALSE (0) otherwise, and FAIL if failure occurs.
3345 
3346  DESCRIPTION
3347     Checks the class name of the given vgroup against the list of internal
3348     vgroup class names, HDF_INTERNAL_VGS.
3349 
3350     There is an exception where the vgroup does not have a class and has a name
3351     set to GR_NAME.  The vgroup is actually an internal vgroup, representing a
3352     GR file.  It was only a very brief gap in the revisions where this scenario
3353     can happen, yet there is at least one test file generated during that
3354     period, grtdfui83.hdf.
3355 *******************************************************************************/
3356 intn
Vgisinternal(int32 vkey)3357 Vgisinternal(int32 vkey /* vgroup's identifier */)
3358 {
3359     CONSTR(FUNC, "Vgisinternal");
3360     vginstance_t *v = NULL;
3361     VGROUP       *vg = NULL;
3362     intn	  is_internal = FALSE;
3363     intn	  ret_value = FALSE;
3364 
3365     /* clear error stack */
3366     HEclear();
3367 
3368     /* Gheck if vgroup is valid */
3369     if (HAatom_group(vkey) != VGIDGROUP)
3370         HGOTO_ERROR(DFE_ARGS, FAIL);
3371 
3372     /* Get instance of vgroup */
3373     if (NULL == (v = (vginstance_t *) HAatom_object(vkey)))
3374         HGOTO_ERROR(DFE_NOVS, FAIL);
3375 
3376     /* Get vgroup itself and check */
3377     vg = v->vg;
3378     if (vg == NULL)
3379         HGOTO_ERROR(DFE_BADPTR, FAIL);
3380 
3381     /* Check for internal class name if it has been set */
3382     if (vg->vgclass != NULL)
3383     {
3384 	int  ii;
3385 
3386 	/* If this class name is one of the internal class name then return
3387 	   TRUE, otherwise, return FALSE */
3388 	ii = 0;
3389 	while (ii < HDF_NUM_INTERNAL_VGS && is_internal == FALSE)
3390 	{
3391             size_t len = HDstrlen(HDF_INTERNAL_VGS[ii]);
3392             if (HDstrncmp(HDF_INTERNAL_VGS[ii], vg->vgclass, len) == 0)
3393 		is_internal = TRUE;
3394 	    ii++;
3395         }
3396     }
3397     else /* no class defined */
3398     {
3399 	/* If class name is not set, check the vgroup's name to catch the case
3400 	   when the vgroup's name was set to GR_NAME.  See HDFFR-1297 (?) for
3401 	   details. -BMR 2012/1/6 */
3402 	/* Check vgroup name */
3403 	if (vg->vgname != NULL)
3404 	    if (HDstrncmp(vg->vgname, GR_NAME, HDstrlen(GR_NAME)) == 0)
3405 		is_internal = TRUE;
3406     }
3407     ret_value = is_internal;
3408 
3409 done:
3410   if(ret_value == FAIL)
3411     { /* Error condition cleanup */
3412     } /* end if */
3413 
3414   /* Normal function cleanup */
3415   return ret_value;
3416 } /* Vgisinternal */
3417 
3418 
3419 /*******************************************************************************
3420  NAME
3421     Visinternal  --  Determine if a vgroup's class name is for internal only
3422  RETURNS
3423     Returns TRUE (1) if "classname" is one of the class names used for
3424     vgroups created by the the library and FALSE (0) otherwise.
3425 
3426  DESCRIPTION
3427     Checks the given name against the list of internal vgroup class names,
3428     HDF_INTERNAL_VGS.
3429 *******************************************************************************/
3430 intn
Visinternal(const char * classname)3431 Visinternal(const char *classname /* vgroup's class name */)
3432 {
3433     int  i;
3434     intn ret_value = FALSE;
3435 
3436     /* Check if this class name is one of the internal class name and return
3437 	TRUE, otherwise, return FALSE */
3438     for (i=0; i < HDF_NUM_INTERNAL_VGS; i++) {
3439         if (HDstrncmp(HDF_INTERNAL_VGS[i], classname, HDstrlen(HDF_INTERNAL_VGS[i])) == 0 ) {
3440             ret_value = TRUE;
3441             break;
3442         }
3443     }
3444     return ret_value;
3445 }
3446 
3447 /*******************************************************************************
3448 NAME
3449     Vgetvgroups -- Get user-created vgroups in a file or in a vgroup
3450 RETURNS
3451     The number of user-created vdatas if successful and FAIL, otherwise.
3452 
3453 DESCRIPTION
3454     Vgetvgroups retrieves n_vgs vgroups by their reference numbers via the
3455     caller-supplied array refarray.  When a vgroup id is specified, Vgetvgroups
3456     will only retrieve the vgroups immediately belong to the specified vgroup,
3457     and not any sub-vgroups.
3458 
3459     The parameter n_vgs provides the number of values that the refarray list
3460     can hold and can be any positive number smaller than MAX_REF (65535).  If
3461     n_vgs is larger than the actual number of user-created vgroups, then only
3462     the actual number of reference numbers will be retrieved.
3463 
3464     The parameter start_vg indicates the vgroup number to start at.
3465     - When start_vg is 0, the retrieval starts at the beginning.
3466     - When start_vg is between 0 and the number of user-created vgroups in
3467       the file or the specified vgroup, Vgetvgroups will start retrieving
3468       vgroups from the vgroup number start_vg.
3469     - When start_vg is greater than the number of user-created vgroups in the
3470       file or the vgroup, Vgetvgroups will return FAIL.
3471 
3472     When refarray argument is NULL, Vgetvgroups will return the actual number
3473     of user-created vgroups without further processing.  This allows application
3474     to find out the size of the array for proper allocation.
3475 
3476     BMR - 2010/07/03
3477 *******************************************************************************/
3478 intn
Vgetvgroups(int32 id,uintn start_vg,uintn n_vgs,uint16 * refarray)3479 Vgetvgroups(int32 id,		/* IN: file id or vgroup id */
3480 	    uintn start_vg,	/* IN: reference number to start retrieving */
3481             uintn n_vgs,	/* IN: number of user-created vgs to return */
3482             uint16 *refarray	/* IN/OUT: ref array to fill */)
3483 {
3484     CONSTR(FUNC, "Vgetvgroups");
3485     vginstance_t *vg_inst = NULL;
3486     int32    vg_ref;
3487     intn     nactual_vgs, user_vgs, ii;
3488     VGROUP  *vg = NULL;
3489     intn     ret_value = SUCCEED;
3490 
3491     /* Clear error stack */
3492     HEclear();
3493 
3494     /* Make sure that proper size is passed in for the non-null array */
3495     if (refarray != NULL && n_vgs == 0)
3496         HGOTO_ERROR(DFE_ARGS, FAIL);
3497 
3498     /* Check if id is a file id */
3499     if (HAatom_group(id) == FIDGROUP)
3500     {
3501 	/* Look through all vgs, searching for user-created vgroups until
3502 	   no more vgroups in the file or the number of vgroups to be
3503 	   retrieved is reached */
3504 	nactual_vgs = 0;/* number of user-created vgroups to be retrieved */
3505 	user_vgs = 0;	/* number of user-created vgroups */
3506 	vg_ref = Vgetid(id, -1);  /* get ref number of first vg in the file */
3507 	while ((vg_ref != FAIL)   /* there are more vgroups */
3508 		&& ((nactual_vgs < n_vgs) || (n_vgs == 0))
3509 		&& (nactual_vgs <= user_vgs))
3510 	{
3511             /* Get instance of vgroup; if it's not found, continue to look for
3512                 other vgroups */
3513             if((vg_inst = vginst(id, (uint16)vg_ref)) == NULL)
3514                 continue;
3515 
3516 	    /* Get vgroup itself and check */
3517 	    vg = vg_inst->vg;
3518 	    if (vg == NULL)
3519 		HGOTO_ERROR(DFE_BADPTR, FAIL);
3520 
3521 	    /* If this vgroup either does not have a class name, which means
3522 		it is a user-created vgroup, or has a class name and the class
3523 		name is not one of the internal class names, then record its
3524 		ref# according to caller's specification of where to start and
3525 		how many to retrieve */
3526 	    if (vg->vgclass == NULL ||
3527 	       (vg->vgclass != NULL && Visinternal(vg->vgclass) == FALSE))
3528 		{
3529 		    /* Make sure to count only from vgroup number start_vg */
3530 		    if (user_vgs >= start_vg)
3531 			/* If caller requests for reference numbers */
3532 			if (refarray != NULL)
3533 			{
3534 			    refarray[nactual_vgs] = (uint16)vg_ref;
3535 
3536 			    /* Increment the actual number of user-created vgs
3537 			       to be retrieved */
3538 			    nactual_vgs++;
3539 			}
3540 		    /* Increment the number of user-created vgs */
3541 		    user_vgs++;
3542 		}
3543 	    /* Move forward to the next vgroup in the file */
3544 	    vg_ref = Vgetid(id, vg_ref);
3545 	} /* while more vgroups in file */
3546 
3547 	/* Flag if start_vg is beyond the number of user-created vgroups */
3548 	if (user_vgs < start_vg)
3549             HGOTO_ERROR(DFE_ARGS, FAIL);
3550 
3551 	/* If caller is asking for the number of vgroups only, return the
3552 	   number of user-created vgroups, otherwise, return the number of
3553 	   vgroups that are actually stored in refarray */
3554 	if (refarray == NULL)
3555 	    ret_value = user_vgs;
3556 	else
3557 	    ret_value = nactual_vgs;
3558     } /* file id is given */
3559 
3560     /* Check if the given is a vgroup id */
3561     else if (HAatom_group(id)==VGIDGROUP)
3562     { /* vgroup id is given */
3563 
3564 	/* Get the number of sub-vgroups belong to this vgroup */
3565 	int32 n_elements = Vntagrefs(id);
3566 	if (n_elements == FAIL)
3567 	    HGOTO_ERROR(DFE_GENAPP, FAIL);
3568 
3569 	/* Get instance of vgroup */
3570 	if (NULL == (vg_inst = (vginstance_t *) HAatom_object(id)))
3571 	    HGOTO_ERROR(DFE_NOVS, FAIL);
3572 
3573 	/* Get vgroup itself and check */
3574 	vg = vg_inst->vg;
3575 	if (vg == NULL)
3576 	    HGOTO_ERROR(DFE_BADPTR, FAIL);
3577 
3578 	/* Go through the tag list vg->tag and find user-created vgroups, until
3579 	   no more sub-vgroups or the number of vgroups to be retrieved is
3580 	   reached */
3581 	nactual_vgs = 0;/* number of user-created vgroups to be retrieved */
3582 	user_vgs = 0;	/* number of user-created vgroups */
3583         for (ii = 0;
3584              ii < n_elements && ((nactual_vgs < n_vgs)|| (n_vgs == 0))
3585                              && (nactual_vgs <= user_vgs);
3586              ii++)
3587         {
3588 	    /* If an element is a vgroup, then get access to it */
3589             if (vg->tag[ii] == DFTAG_VG)
3590 	    {
3591 		vginstance_t *subv_inst = NULL;
3592 		VGROUP       *subvg = NULL;
3593 
3594                 /* Get instance of vgroup; if it's not found, continue to
3595 		   other vgroups */
3596                 if((subv_inst = vginst(vg->f, (uint16)vg->ref[ii])) == NULL)
3597                     continue;
3598 
3599 		/* Get vgroup itself and check */
3600 		subvg = subv_inst->vg;
3601 		if (subvg == NULL)
3602 		    HGOTO_ERROR(DFE_BADPTR, FAIL);
3603 
3604 		/* If this vgroup is internally created by the lib, then just
3605 		   skip it; otherwise, record its ref# according to caller's
3606 		   specification of where to start and how many to retrieve */
3607 		if (subvg->vgclass != NULL)
3608 		{
3609 		    /* Make sure this vgroup is not an internal one */
3610 		    if (Visinternal(subvg->vgclass) == FALSE)
3611 		    {
3612 			/* Make sure to count only from vg number start_vg */
3613 			if (user_vgs >= start_vg)
3614 			    /* If caller requests for reference numbers */
3615 			    if (refarray != NULL)
3616 			    {
3617 				refarray[nactual_vgs] = (uint16)vg->ref[ii];
3618 
3619 				/* Increment the actual number of user-created
3620 				   vgs to be retrieved */
3621 				nactual_vgs++;
3622 			    }
3623 
3624 			/* Increment the number of user-created vgs */
3625 			user_vgs++;
3626 		    }
3627 		}
3628 	    } /* this sub element is a vgroup */
3629         } /* for */
3630 
3631 	/* Flag if start_vg is beyond the number of user-created vgroups */
3632 	if (user_vgs < start_vg)
3633 	    HGOTO_ERROR(DFE_ARGS, FAIL);
3634 
3635 	/* If caller is asking for the number of vgroups only, return the
3636 	   number of user-created vgroups, otherwise, return the number of
3637 	   vgroups that are actually stored in refarray */
3638 	if (refarray == NULL)
3639 	    ret_value = user_vgs - (intn)start_vg;
3640 	else
3641 	    ret_value = nactual_vgs;
3642     } /* vgroup id is given */
3643     else
3644     {
3645  	fprintf(stderr, "The given ID must be a file ID or a vgroup ID\n");
3646         HGOTO_ERROR(DFE_ARGS, FAIL);
3647     }
3648 done:
3649   if(ret_value == FAIL)
3650     { /* Error condition cleanup */
3651 
3652     } /* end if */
3653 
3654   /* Normal function cleanup */
3655   return ret_value;
3656 }   /* Vgetvgroups */
3657