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